我使用以下代码片段(在Xcode 13 Beta 5
和部署目标设置为 14.0)根据 iOS 版本有条件地应用视图修饰符:
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)
}
}
只要我不使用 iOS 15 的视图修饰符,此代码就可以很好地工作,但是如果我想使用这些修饰符中的任何一个(例如Task
for ex.),那么我需要使用#available
指令,这是我不想选择的选项,因为我的代码库很大,有很多部分应该采用新的 iOS 15 修饰符,并且通过#available
在代码中的任何地方使用它会使它看起来像一盘千层面。
如何使这段代码以一种干净的方式编译而不使用#available
检查?