这里每天分享一个 iOS 的新知识,快来关注我吧
前言
小组件系列传送门:
iOS 小组件开发第一篇:基础介绍
iOS 小组件开发第二篇:时间线
iOS 小组件开发第三篇:实战
iOS 小组件开发第四篇:小组件的尺寸
iOS 小组件开发第五篇:开发可配置的小组件
iOS 小组件开发第六篇:点击事件和交互
iOS 小组件开发第七篇:锁屏小组件
iOS 小组件开发第八篇:灵动岛开发
iOS 小组件开发第九篇:在 iOS 17 上创建可交互的小组件
iOS 小组件开发第十篇:小组件动画
当你的项目中已有小组件使用 Xcode 15 编译安装的时候,可能会看到一些不符合预期的情况,这是因为 Xcode 15 中更改了一些小组件的内部策略,以及提供了一些新的 API,今天来讲讲如何兼容这些情况。
containerBackground API
如果你的小组件有使用 background
来设置背景颜色,那么在添加小组件的时候可能会收到这个错误:
苹果提示需要适配 containerBackground API
,这是 iOS 17 新出的一个用来填充 View 背景颜色的接口,因为今年开始苹果把小组件带到了整个苹果生态中,包括 macOS Sonoma,也包括锁屏的 StandBy 模式。
在一些特殊的场景下,苹果不希望开发者自己自定义背景颜色,比如 StandBy 模式,有背景颜色会看起来非常突兀,为了兼容这种情况,苹果才推出了这个新的 API。
要适配这个 API 也非常简单,只需要把 background
改成 containerBackground
,但是 containerBackground
在 iOS 17 可用,如果你的小组件支持 iOS 17 以下,这里就会报错。所以可以通过给 View 增加一个扩展的方式来兼容:
swift
extension View {
func widgetBackground(_ backgroundView: some View) -> some View {
// 如果是 iOS 17,则使用 containerBackground
if #available(iOSApplicationExtension 17.0, *) {
return containerBackground(for: .widget) {
backgroundView
}
} else {
return background(backgroundView)
}
}
}
在设置背景颜色的时候就可以直接使用这个新方法了:
scss
struct MyWidgetEntryView : View {
var entry: Provider.Entry
var body: some View {
VStack {
Spacer()
HStack {
Spacer()
Text(entry.date, style: .time)
Spacer()
}
Spacer()
}
.widgetBackground(backgroundView: Color.red)
}
}
再次运行程序,发现提示已经消失了。
边距问题
当你试图使用一个 View 将小组件完全填充时,可能会发现有一部分边距始终无法填充,类似下边这样:
这是因为在 iOS 17 中小组件默认把安全区域改成了一个默认的边距,可以使用新的 API contentMarginsDisabled
来禁用这个默认的边距,同样这个方法只支持 iOS 17,因此仍然需要写个扩展来兼容:
swift
extension WidgetConfiguration {
func disableContentMarginsIfNeeded() -> some WidgetConfiguration {
if #available(iOSApplicationExtension 17.0, *) {
return self.contentMarginsDisabled()
} else {
return self
}
}
}
注意这个方法是作用在 WidgetConfiguration
上的,所以使用的时候应该写在这里:
less
struct MyWidget: Widget {
let kind: String = "MyWidget" // 唯一标识
var body: some WidgetConfiguration {
StaticConfiguration(kind: kind, provider: Provider()) { entry in
MyWidgetEntryView(entry: entry)
}
.configurationDisplayName("这是小组件的名称")
.description("这是小组件的描述.")
.supportedFamilies([.systemSmall, .systemMedium, .systemLarge])
.disableContentMarginsIfNeeded()
}
}
再次运行程序,发现边距消失了,一切回归正常 。
这里每天分享一个 iOS 的新知识,快来关注我吧
本文同步自微信公众号 "iOS新知",每天准时分享一个新知识,这里只是同步,想要及时学到就来关注我吧!