The Swift compiler is aware of API availability within an if #available()
block:
// Compiling with a deployment target of iOS 16:
if #available(iOS 17, *) {
someiOS17API()
}
else {
olderAPI()
}
The compiler allows us to call the iOS 17 API within the if #available
block, because it knows that block will only run on iOS 17 or later. However, we cannot currently do the same thing with closure arguments. For example, here's how I might use it with SwiftUI:
extension View {
/// Modifies a view only if running on iOS 17 or later
func iOS17(_ block: @available(iOS 17, *) (Self)->some View) -> some View {
if #available(iOS 17, *) {
return block(self)
} else {
return self
}
}
}
// Usage:
Text("Hello")
.iOS17 { view in
// The compiler would know that this block only runs on
// iOS 17+, so it allows us to use this modifier here
view.someiOS17Modifier()
}
Because of the chained nature of SwiftUI APIs, it's not easy to use an if #available
block here directly. Being able to annotate the closure parameters would make for a significantly nicer API.
What do you think?