iOS14 新特性-WidgetKit 小部件 通过桌面编辑添加,将小部件放在 iOS 主屏幕或 macOS 通知中心上,使用户可以随时访问应用中的内容。同时小部件也可以保持更新,因此用户始终可以一目了然地获得最新信息,同时点击区域可以 Deep Link 跳转到主 APP 任意界面中。
在 2020 年苹果发布会推出 Widget 之后,贝壳就第一时间做出了尝试, 期间苹果中国提供了很多支持与帮助,目前已在贝壳和链家 APP 上线。
小部件具有三种不同的大小(小,中和大),可以显示各种信息。用户可以个性化小部件以查看特定于其需求的详细信息,并以最适合他们的方式安排其小部件。
不同分辨率机型,三种卡片的尺寸也不同:
1 如何开发 WidgetKit?
前期准备:
Xcode 12 及 Bate 版, iOS 14 及 Bate 版, 了解 SwiftUI 控件
1.1 创建 Widget
首先,File->New->Target:
有两种配置可供选择:
StaticConfiguration: 对于一个没有用户可配置属性的Widget。
例如,显示一般市场信息的股票市场 Widget,或显示趋势标题的新闻 Widget。
IntentConfiguration: 对于一个具有用户可配置属性的Widget来说,你可以使用SiriKit自定义意图来定义属性。您使用 SiriKit 自定义意图来定义属性。
例如,一个天气 Widget 需要一个城市的邮政编码或邮政编码,或者一个包裹跟踪 Widget 需要一个跟踪号码。
下图中「Include Configuration Intent」复选框决定了 Xcode 使用哪种配置。选择 Include Configuration Intent 表示支持用户配置;不需要,则不勾选。
1.2 Widget 初始化配置
对象解析
kind :
识别 Widget 的字符串。
如果包含多个 widget 后可作为唯一的标识符。
Provider :
符合 TimelineProvider 的对象。
一个符合 TimelineProvider 的对象,它能产生一个时间线,告诉 WidgetKit 何时渲染 Widget。
时间线包含一个你定义的自定义 TimelineEntry 类型。
时间线条目标识了你希望 WidgetKit 更新 Widget 内容的日期。
在自定义类型中包含你的 Widget 的视图需要渲染的属性。
Placeholder :
一个 SwiftUI 视图,WidgetKit 用来在第一次渲染 Widget。
占位符是您的 Widget 的通用表示,没有特定的配置或数据。
Content Closure(内容闭合) :
一个包含 SwiftUI 视图的封闭。
WidgetKit 调用它来渲染 Widget 的内容,从提供者那里传递一个 TimelineEntry 参数。
函数解析
1) placeholder
占位视图,在数据加载前展示,在 xcode12 bate3 和 bate4 中有所有所变化:
2) getSnapshot
快照,在添加组件库中展示
3) getTimeline
时间轴,控制刷新时机
4) SimpleEntry
数据模型,类似 model
5) WidgetEntryView
主内容,展示区分小中大卡片 ,可根据 family 来区分
6) Widget
主界面控制器。kind 为标识符
Preview 预览
界面开发是 SwiftUI (Apple 要求),可参考:https://developer.apple.com/documentation/widgetkit/creating-a-widget-extension
1.3 Widget 刷新机制
自动刷新
如下图,本身维护一个时间轴,在创建时填充不同时间节点,当到达时间节点位置时,触发刷新。after 会在消耗完时间点后,再次填充,保持循环运行。
手动刷新
一种是 push notification 推送来更新 widget,另一种则是客户端内通过调用接口主动 reload。
2 OC 项目和 Swift 混编
如果原有老项目为 OC 项目,想要实现和 Swift 的相互调用,需用到桥接文件,另外针对引入 Swift 依赖库,会引起包体积增加,大小大概 7~8M 左右,可以在 ipa 包内查看:
2.1 Swift 引用 OC 代码
创建 xxx(工程名)-Bridging-Header 头文件, 并在 Build Setting -> Objective-C Bridging Header 设置其路径
这样我们在桥接文件内,通过 import “xxx.h”引用 OC 的组件库,就可以在 Swift 使用了。
2.2 OC 引用 Swift 代码
桥接文件不需要手动创建,系统帮我创建好了,可以查看 xxx-swift,在文件夹查找不到,但是引用头文件后,可以点击进入查看:
3 主 APP 和 Widget 间通信
因为 Widget 为新的 Target 项目,和之前主项目是两个进程的关系,所以如果想要资源共享,比如登录状态值 token, 网络配置等,就需要用到共享区域来实现通信。苹果提供的共享方式有:
方式一:APPGroup 方式
1) 配置好证书,是 Gourp 功能正常使用中,主 APP 和 Widget 保持统一 key
当我们配置完以后,会在文件目录下多出来一个.entitlements 的文件。
2)主 APP 写下数据
3)Widget 内读取 App Group 的共享目录
方式二:KeyChain Sharing
KeyChain 可将用户信息加密存储在钥匙串中,保证用户信息的安全性;另外多个应用可通过 keyChain 共享用户信息。
1)同样我们需要配置 keychan 的 key, 保持和主 APP 一致,省事的是少了证书的配置
2)通过对钥匙串的读写来操作 (一般由 SAKeychain 库管理)比较方便,注意一点:实现共享的只是在钥匙串的缓存数据,如果一旦加载到内存中,它的修改不受主 APP 的影响了。
4 常见问题
问题 1 . 选择 Intent (widget 配置),会出现 configtion 查找不到
解决:
方法一: 若不使用 Inetent, 在生成 widget 时不勾选即可,避免这类问题;
方法二:见https://developer.apple.com/forums/thread/653910 (在官网提出后,目前没有官方人员回答,不过有其他答案,未验证)
问题 2 . Xcode 12 bate3 运行贝壳的 widget 未显示 preview
解决:Build systems: 选择新的编译方式
问题 3 . 由于 WidgetKit 使用一些 Swift 的新特性,所以版本需要修改成 Swift5.0
问题 4 . Swift 桥接 OC 组件库
解决:
1) 生成 LJShell-Bridging-Header.h 桥接文件,
2)在 Build setting 中找到 Objective-C Bridging Header 设置对应路径 $
(SRCROOT)/LianJiaShell/LJShell-Bridging-Header.h
3)将 Build Settings 中的 Defines Module 选项设置为 YES
问题 5 . 引入 OC 组件库报查找不到
解决:在 podfile 中在 LJWidget 的 target 引入对应 pod xxx
问题 6 . 使用 Widget Preview 功能
bate 版本目前发现在 OC 工程下混编情况,prview 无法使用,可以尝试新建个 swift 工程来编写 swiftUI,使用 preview 功能
问题 7 . Error: Multiple commands produce
解决:
方法一:
不使用 New Build System,在 File > Project/Workspace Settings 中的 Share Project/Workspace Settings 里 build system 将 New Build System(Default)切换成 Legacy build system。
方法二:在 target -> Build phase > Copy Bundle Resource 中找到 info.plist,移除
问题 8 . dyld: Library not loaded:
解决:https://developer.apple.com/forums/thread/126506
5 参考文献
WidgetKit:
https://developer.apple.com/documentation/widgetkit
SwiftUI:
https://developer.apple.com/tutorials/swiftui/creating-and-combining-views
本文转载自公众号贝壳产品技术(ID:beikeTC)。
原文链接:
评论 1 条评论