Last active
January 29, 2024 17:34
-
-
Save jeffypooo/1e7e20096c1f759d4c7aef99e54e004d to your computer and use it in GitHub Desktop.
How to determine PresentationDetent type in SwiftUI (pre-iOS 16.4).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extension PresentationDetent { | |
/// Converts a `PresentationDetent` to an `ExpandableSheetDetent` | |
/// NOTE: Detents created using `.custom(_)` will fail to convert. | |
var expandableSheetDetent: ExpandableSheetDetent { | |
if self == .medium { return .medium } | |
if self == .large { return .large } | |
if let height = heightValue { return .height(height) } | |
if let fraction = fractionValue { return .fraction(fraction) } | |
| |
let unknownType = type(of: self) | |
fatalError("cannot convert \(unknownType) to ExpandableSheetDetent") | |
} | |
| |
/// Derived height value for a detent created with `.height` case. | |
var heightValue: CGFloat? { extractValueFromDescription(key: "height") } | |
| |
/// Derived fraction value for a detent created with `.fraction` case. | |
var fractionValue: CGFloat? { extractValueFromDescription(key: "fraction") } | |
| |
/// Extracts a value from the description of a detent created with `.height` or `.fraction` cases. Yes, | |
/// this is seriously the only way to do this pre-iOS 16.4 release. I'm sorry. | |
/// | |
/// Assumption the description is formatted like so: | |
/// ``` | |
/// "PresentationDetent(id: SwiftUI.PresentationDetent.Identifier.fraction(0.6))" | |
/// // or | |
/// "PresentationDetent(id: SwiftUI.PresentationDetent.Identifier.height(50))" | |
/// ``` | |
/// | |
/// - Parameter key: The key to extract the value for | |
/// - Returns: The extracted value | |
private func extractValueFromDescription(key _: String) -> CGFloat? { | |
let desc = "\(self)" | |
/// Look for numbers (fp or integers) that will be in the description string | |
/// The description prints out in canonical format, with the bit we are interested in looking like so: | |
/// `<large|medium|fraction(0.5)|height(100)>` | |
let pattern = #"[\d.]+(?=\))"# | |
guard | |
let regex = try? Regex(pattern), | |
let match = try? regex.firstMatch(in: desc), | |
let doubleValue = Double(match.first?.substring ?? "") | |
else { return nil } | |
| |
return CGFloat(doubleValue) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment