本篇是用户可编辑的 Widget
先来看效果图
建议将 demo 下载下来对照着看对应 demo 里的 AnimalWidget 文件
1. 新建 Widget Extension,勾选 Intent。
1. 新建 Widget Extension,勾选 Intent
2. 点击 AnimalWidget.intentdefinition 文件 添加可编辑的数据类型 具体操作看图吧
2. 点击 AnimalWidget.intentdefinition 文件 具体操作看图吧
3. 为第二步新增的数据类型 设置对应的值
4. 编辑 Info.plist (️是 widget extension 的 Info.plist )
<key>NSExtension</key>
<dict>
<key>IntentsSupported</key>
<array>
<string>AnimalWidgetConfigurationIntent</string>
</array>
<key>NSExtensionAttributes</key>
<dict>
<key>IntentsRestrictedWhileLocked</key>
<array/>
<key>IntentsRestrictedWhileProtectedDataUnavailable</key>
<array/>
<key>IntentsSupported</key>
<array>
<string>AnimalWidgetConfigurationIntent</string>
</array>
</dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.intents-service</string>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).IntentHandler</string>
</dict>
4. 编辑 Info.plist (️是 widget extension 的 Info.plist )
5. 创建 IntentHandler.swift 添加一下代码 (可能会报错 找不到 AnimalWidgetConfigurationIntentHandling 、AnimalWidgetConfigurationIntent 先不管先把别的配置好)
import Intents
/// 自己创建的文件
class IntentHandler: INExtension, AnimalWidgetConfigurationIntentHandling { // AnimalWidgetConfigurationIntentHandling 是第二步的名字 加上 IntentHandling 后缀
/// 配置给用户可选的列表 AnimalWidgetConfigurationIntent 是第二步的名字 加上 Intent 后缀
func provideAnimalOptionsCollection(for intent: AnimalWidgetConfigurationIntent, searchTerm: String?, with completion: @escaping (INObjectCollection<Animal>?, Error?) -> Void) {
/// 这里可以去请求网络拿数据
///搜索词 searchTerm 搜索cat
if searchTerm == "cat" {
completion(INObjectCollection(items: [Animal(identifier: "cat", display: "cat")]), nil)
}
let animals: [Animal] = XXXAnimal.zoo.map { (xxxAnimal) in
return Animal(identifier: xxxAnimal.id, display: xxxAnimal.name)
}
completion(INObjectCollection(items: animals), nil)
}
override func handler(for intent: INIntent) -> Any {
return self
}
}
6. 修改 AnimalWidget.swift 内容
如果你的工程已经存在了一个 Widget 将 @main 去掉
使用下面
//我的这部分代码在 XXXWidget.swift
@main
struct AllWidget: WidgetBundle {
@WidgetBundleBuilder
var body: some Widget {
XXXWidget()
AnimalWidget()
}
}
修改 TimelineEntry
struct SimpleEntry: TimelineEntry {
let date: Date
let configuration: ConfigurationIntent
}
--------------原️----新️-----------------
/// 重新命名 去掉 let configuration: ConfigurationIntent (也可以保留但类型是 AnimalWidgetConfigurationIntent)
///增加自己需要的参数
struct AnimalSimpleEntry: TimelineEntry {
let date: Date
/// 新加自己需要的参数
let animal: XXXAnimal
}
修改 IntentTimelineProvider
️ 涉及到 AnimalWidgetConfigurationIntent 可能会报错 先不管 ️
struct Provider: IntentTimelineProvider {
func placeholder(in context: Context) -> SimpleEntry {
SimpleEntry(date: Date(), configuration: ConfigurationIntent())
}
func getSnapshot(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (SimpleEntry) -> ()) {
let entry = SimpleEntry(date: Date(), configuration: configuration)
completion(entry)
}
func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
var entries: [SimpleEntry] = []
// Generate a timeline consisting of five entries an hour apart, starting from the current date.
let currentDate = Date()
for hourOffset in 0 ..< 5 {
let entryDate = Calendar.current.date(byAdding: .hour, value: hourOffset, to: currentDate)!
let entry = SimpleEntry(date: entryDate, configuration: configuration)
entries.append(entry)
}
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
}
}
--------------原️----新️-----------------
// 重新命名
struct AnimalProvider: IntentTimelineProvider {
// 按照要求增加 Entry 和 Intent
typealias Entry = AnimalSimpleEntry
typealias Intent = AnimalWidgetConfigurationIntent
func placeholder(in context: Context) -> AnimalSimpleEntry {
AnimalSimpleEntry(date: Date(), animal: .lion)
}
func getSnapshot(for configuration: AnimalWidgetConfigurationIntent, in context: Context, completion: @escaping (AnimalSimpleEntry) -> ()) {
let entry = AnimalSimpleEntry(date: Date(), animal: .lion)
completion(entry)
}
func getTimeline(for configuration: AnimalWidgetConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
let currentDate = Date()
guard let id = configuration.animal?.identifier, let entryDate = Calendar.current.date(byAdding: .minute, value: 1, to: currentDate) else {
let timeline = Timeline(entries: [AnimalSimpleEntry(date: currentDate, animal: .lion)], policy: .atEnd)
completion(timeline)
return
}
let entry = AnimalSimpleEntry(date: entryDate, animal: XXXAnimal.animal(id, color: configuration.color))
let timeline = Timeline(entries: [entry], policy: .atEnd)
completion(timeline)
}
}
其他地方对照 demo 修改就可以了
️如果有 Cannot find type 'AnimalWidgetConfigurationIntent' in scope 报错 尝试多 build 几次或者 重启 Xcode️