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

相关推荐
QuantumLeap丶6 小时前
《Flutter全栈开发实战指南:从零到高级》- 09 -常用UI组件库实战
flutter·ios·dart
2501_915918417 小时前
App 上架苹果商店全流程详解 从开发者账号申请到开心上架(Appuploader)跨平台免 Mac 上传实战指南
macos·ios·小程序·uni-app·objective-c·cocoa·iphone
2501_916007478 小时前
从零开始学习iOS App开发:Xcode、Swift和发布到App Store完整教程
android·学习·ios·小程序·uni-app·iphone·xcode
Pluto53812 小时前
第一个app产品的迭代
ios·github
HarderCoder13 小时前
Swift 中的不透明类型与装箱协议类型:概念、区别与实践
swift
HarderCoder13 小时前
Swift 泛型深度指南 ——从“交换两个值”到“通用容器”的代码复用之路
swift
2501_9159214313 小时前
iOS 26 CPU 使用率监控策略 多工具协同构建性能探索体系
android·ios·小程序·https·uni-app·iphone·webview
狂团商城小师妹13 小时前
JAVA国际版同城打车源码同城服务线下结账系统源码适配PAD支持Android+IOS+H5
android·java·ios·小程序·交友
游戏开发爱好者813 小时前
iOS 应用逆向对抗手段,多工具组合实战(iOS 逆向防护/IPA 混淆/无源码加固/Ipa Guard CLI 实操)
android·ios·小程序·https·uni-app·iphone·webview
东坡肘子14 小时前
惊险但幸运,两次!| 肘子的 Swift 周报 #0109
人工智能·swiftui·swift