I use the following code snippet (in Xcode 13 Beta 5
and deployment target set to 14.0) to apply view modifiers conditionally according to iOS version:
struct ContentView: View {
var body: some View {
Text("Hello, world!")
.modifyFor(iOS14: {
$0.onAppear {
//do some stuff
}
}, iOS15: {
$0.task { //<---- Error: 'task(priority:_:)' is only available in iOS 15.0 or newer
//do some stuff
}
})
}
}
struct CompatibleView<Input: View,
Output14: View,
Output15: View>: View {
var content: Input
var iOS14modifier: ((Input) -> Output14)?
var iOS15modifier: ((Input) -> Output15)?
@ViewBuilder var body: some View {
if #available(iOS 15, *) {
if let modifier = iOS15modifier {
modifier(content)
}
else { content }
}
else {
if let modifier = iOS14modifier {
modifier(content)
}
else { content }
}
}
}
extension View {
func modifyFor<T: View, U: View>(iOS14: ((Self) -> T)? = nil,
iOS15: ((Self) -> U)? = nil) -> some View {
CompatibleView(content: self,
iOS14modifier: iOS14,
iOS15modifier: iOS15)
}
}
this code works great as long as I don't use iOS 15's view modifiers, but if I want to use any of those modifiers (like Task
for ex.) then I need to use the #available
directive which's an option I don't wanna opt in, because my codebase is large, there are many parts that should adopt the new iOS 15 modifiers and by using #available
everywhere in the code will make it looks like a dish of Lasagna.
how to make this piece of code compiles in a clean way and without using the #available
check ?
() -> View
or(View) -> View
! How could be not an issue?! – Redeemer.task
modifier) and it compiles. – Harless.if(.iOS18) {}
– Titer