这儿每天共享一个 iOS 的新知识,快来重视我吧
前语
最近开始正式运用 SwiftUI 做项目了,但是发现了一个很大的问题,便是很多在 UIKit 中经常用的 API,在 SwiftUI 中需求很高的版别才能运用。
随便举几个比如,ScrollView
滚动关闭键盘的 keyboardDismissMode
特点,在 UIScrollView 中 iOS 7 就支撑了,但在 SwiftUI 中 iOS 16 才支撑。再比方,在 UIAlertController
上添加 TextField
,在 UIKit 中 iOS 8 就支撑,但在 SwiftUI 上,iOS 16 才支撑。
所以现阶段不太可能用纯 SwiftUI 做项目,除非你的项目最低兼容 iOS 15,甚至是 16 以上。话说回来,在一些 API 低版别不支撑的状况下,就需求用到一些兼容手段,最近看到了一些聪明的办法共享给我们。
过错的兼容办法
我们假设你的项目最低版别支撑 iOS 14,在运用一些 14 上不兼容的 API 时会报错:
能够看到 cyan
这个颜色在 iOS 15 才能运用,有一种办法是添加在这个 VStack
下添加 #available
判别:
var body: some View {
if #available(iOS 16.0, *) {
VStack {
Text("Hello, world!")
.fontWeight(.bold)
.background(Color.red)
.foregroundColor(.blue)
.padding()
.frame(width: 100, height: 100)
Text("Hello, world!")
.fontWeight(.bold)
.background(Color.red)
.padding()
.frame(width: 100, height: 100)
.foregroundColor(.cyan)
}
} else {
VStack {
Text("Hello, world!")
.fontWeight(.bold)
.background(Color.red)
.foregroundColor(.blue)
.padding()
.frame(width: 100, height: 100)
Text("Hello, world!")
.fontWeight(.bold)
.background(Color.red)
.padding()
.frame(width: 100, height: 100)
.foregroundColor(.blue)
}
}
}
这种计划有几个问题,首要为了运用 cyan
,整个 VStack
都要被 if 句子包裹起来,假如这个 VStack
下代码非常多的话,会有很多的重复代码。其次这种办法不利于保护,假如再有一个特点是 iOS 16 才能用的,那么再用 if iOS 16
包裹一次吗?显然不合理。
正确的做法
正确的办法是经过扩展做兼容,我们能够给 Color
扩展出一个新的 newCyan
特点,来兼容这种状况:
extension Color {
static let newCyan: Self = {
if #available(iOS 15.0, *) {
return .cyan
} else {
return .black
}
}()
}
这样的话,再运用的时分直接运用 newCyan
就行了:
Text("Hello, world!")
.foregroundColor(.newCyan)
这样就处理了上边的问题。
其他的比如
运用扩展的兼容计划是个不错的思路,还有一些其他比如:
1、隐藏 List 的分割线 listRowSeparator
办法,在 iOS 15 才能用:
同样运用扩展:
func newHiddenListRowSeparator() -> some View {
if #available(iOS 15.0, *) {
return listRowSeparator(.hidden)
} else {
return self
}
}
hiddenListRowSeparator
改成 newHiddenListRowSeparator
即可。
2、ScrollView 禁止滚动
func newScrollDisabled() -> some View {
if #available(iOS 16.0, *) {
return self.scrollDisabled(true)
} else {
return self
}
}
3、View 的 tint 办法 iOS 15 以上才能用
那就给 View 写个扩展
extension View {
func newTint(_ color: Color?) -> some View {
if #available(iOS 16.0, *) {
return self.tint(color)
} else {
return self.accentColor(color)
}
}
}
总结
运用扩展兼容 API 的办法优点清楚明了:
-
处理了重复代码问题
-
每个 API 的兼容判别都是独立的,可保护性强
-
当你晋级最低版别时,只需求把版别判别删掉或者直接把办法名改掉即可
这儿每天共享一个 iOS 的新知识,快来重视我吧