前言
本文具有强烈的个人感情色彩,如有观看不适,请尽快关闭. 本文仅作为个人学习记录使用,也欢迎在许可协议范围内转载或分享,请尊重版权并且保留原文链接,谢谢您的理解合作. 如果您觉得本站对您能有帮助,您可以使用RSS方式订阅本站,感谢支持!
问题
最近在开发iOS17上的小组件使用SwiftUI框架,第一次进行工程化遇到一个 api可用性检测问题
之前的小组件是锁屏小组件,在iOS16上运行,最近iOS17更新了新内容,导致运行起来之后被提示需要增加
1
containerBackground(.red.gradient, for: .widget)
这样的适配容器,这就导致 在iOS16上的api some View
要使用iOS17的API
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ZStack(alignment: .bottomTrailing) {
Image("widget_clock")
.resizable()
.aspectRatio(contentMode: .fill)
VStack(spacing: 0) {
Text("\(entry.date.hour)")
Text("\(entry.date.min)")
}
.font(.system(size: 60, weight: .bold))
.foregroundColor(.white)
}
. if #available(iOSApplicationExtension 17.0, *) { //这行代码报错 告知我不能这样做 不识别if
$0.containerBackground(.red.gradient, for: .widget)
} else {
// Fallback on earlier versions
}
研究半天 发现还得给view扩展一个返回自己的函数来链式配置.
这写法真是不太明白咋写合适最终只能 给View写个extension
1
2
3
4
5
6
7
8
9
import Foundation
import SwiftUI
public extension View {
func modify<Content>(@ViewBuilder _ transform: (Self) -> Content) -> Content {
transform(self)
}
}
然后使用的时候
1
2
3
4
5
6
7
.modify{
if #available(iOSApplicationExtension 17.0, *) {
$0.containerBackground(.red.gradient, for: .widget)
} else {
// Fallback on earlier versions
}
}
这样在swiftUI的 body 里面才能顺利编译通过
完整的测试代码如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
struct MomentsWidget: Widget {
let kind: String = WidgetType.moments.kind
var body: some WidgetConfiguration {
IntentConfiguration(kind: kind, intent: ConfigurationIntent.self, provider: MomentsWidgetProvider()) { entry in
MomentsWidgetEntryView(entry: entry)
.modify{ //这里是适配代码
if #available(iOSApplicationExtension 17.0, *) {
$0.containerBackground(.white.gradient, for: .widget)
} else {
// Fallback on earlier versions
}
}
}
// 这里定义的就是小组件弹出界面中的标题与副标题
.configurationDisplayName("好友动态")
.description("通过该组件可以创建好友动态列表")
.supportedFamilies([.systemLarge])
}
}
总结
1.写swiftUI感觉像是第一次接触UIKit时候那样 一开始比较困难时因为对它缺少认知
2.swiftUI的框架设计应该把这种问题考虑进去 提供一个专用的API,或者至少不要让Xcode的提示出错吧,Xcode提供的东西都出错只能说明这个东西还不成熟.