iOS 小组件开发第十二篇:iOS 17 适配

这里每天分享一个 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新知",每天准时分享一个新知识,这里只是同步,想要及时学到就来关注我吧!

相关推荐
a44931536212 小时前
iPhone 基带故障诊断——无服务/搜索不到网络的芯片级维修实录
网络·macos·ios·电脑·iphone
程序员老刘13 小时前
Flutter版本选择指南:3.44密集修BUG,9月大限将至 | 2026年7月
flutter·ai编程·客户端
Summer-Bright14 小时前
消费者 AI 变现竞争:从“一家独大“到“iOS vs Android“,谁在为 AI 买单?
android·人工智能·ios·ai·自然语言处理·agi
a44931536215 小时前
iPhone 充电故障的全链路诊断——从 Lightning/USB-C 接口到 Tristar 充电 IC
c语言·macos·ios·电脑·硬件架构·iphone
AaronMan1 天前
iOS 中的 Subscription 与 RACDisposable:订阅生命周期管理
ios
代码的小搬运工2 天前
【iOS】天气预报仿写总结
ios·objective-c·cocoa
代码的小搬运工2 天前
【iOS】3G-Share仿写总结
macos·ios·cocoa
Lvan的前端笔记2 天前
SwiftUI:iOS 常用视图组件速查
ios·swiftui·swift
2501_916007472 天前
iOS和macOS应用程序性能分析和优化工具使用综合指南
android·macos·ios·小程序·uni-app·iphone·webview