Skip to content

Instantly share code, notes, and snippets.

@jeffypooo
Last active January 29, 2024 17:34
Show Gist options
  • Save jeffypooo/1e7e20096c1f759d4c7aef99e54e004d to your computer and use it in GitHub Desktop.
Save jeffypooo/1e7e20096c1f759d4c7aef99e54e004d to your computer and use it in GitHub Desktop.
How to determine PresentationDetent type in SwiftUI (pre-iOS 16.4).
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