引言
经过前面几篇文章阅读,已经掌握开发一款小组件的基本技能了,接下来开始掌握一些相对高级一点的技能。本文创建一个可配置小组件,通过修改时间类型,让Text空间显示不同格式的时间。
本文大纲
- 添加动态配置 Custom Intent Definition
- 可配置小组件框架代码解析
- 修改 .intentdefinition 文件实现修改时间类型
- 代码读取配置信息,实现动态布局
添加动态配置
方式1:新建组件的时候勾选 “Include Configuration Intent” 复选框。
方式2:在您的Xcode项目中,选择“File”>“New File”,然后选择“SiriKit Intent Definition File”。单击”Next“,并在出现提示时保存文件。Xcode在项目中会生成一个新的.intentdefinition 文件。
可配置小组件框架代码解析
如果默认用方式1 创建组件,代码如下,如果通过方式2,请参考下面的代码对应修改即可,注释中已经标明与普通小组件代码的不同点。
//
// WidgetConfigIntent.swift
// WidgetConfigIntent
//
import WidgetKit
import SwiftUI
import Intents
struct Provider: IntentTimelineProvider {
func placeholder(in context: Context) -> SimpleEntry {
// 不同点3:传递默认参数
SimpleEntry(date: Date(), configuration: ConfigurationIntent())
}
// 不同点4:比使用StaticConfiguration时多了一个配置参数
func getSnapshot(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (SimpleEntry) -> ()) {
let entry = SimpleEntry(date: Date(), configuration: configuration)
completion(entry)
}
// 不同点5:比使用StaticConfiguration时多了一个配置参数
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 SimpleEntry: TimelineEntry {
let date: Date
// 不同点2: 多了一个配置参数,小组件编辑界面设置参数会通过这个传递进来
let configuration: ConfigurationIntent
}
struct WidgetConfigIntentEntryView : View {
var entry: Provider.Entry
var body: some View {
Text(entry.date, style: .time)
}
}
// 小组件入口
@main
struct WidgetConfigIntent: Widget {
let kind: String = "WidgetConfigIntent"
var body: some WidgetConfiguration {
//不同点1: 这里使用 IntentConfiguration, 对比 StaticConfiguration
//这里还多了一个参数 intent: ConfigurationIntent.self
IntentConfiguration(kind: kind, intent: ConfigurationIntent.self, provider: Provider()) { entry in
WidgetConfigIntentEntryView(entry: entry)
}
.configurationDisplayName("可配置小组件")
.description("选择不同的时间类型")
}
}
// 调试预览
struct WidgetConfigIntent_Previews: PreviewProvider {
static var previews: some View {
WidgetConfigIntentEntryView(entry: SimpleEntry(date: Date(), configuration: ConfigurationIntent()))
.previewContext(WidgetPreviewContext(family: .systemSmall))
}
}
修改 .intentdefinition 文件实现修改时间类型
- 修改配置名称为TimeTypeConfiguration
- 添加参数类型TimeTypeEnum,这里先用枚举类型
- 添加参数timeType参数,类型指定为TimeTypeEnum
代码读取配置信息,实现动态布局
现在编译应该不通过,需要修改一下WidgetConfigIntent.swift中的代码
- 把代码中 ConfigurationIntent 替换为 TimeTypeConfigurationIntent(希望到这里你能领悟到点什么)
运行代码,在桌面添加组件,长按组件 > 编辑小组件可以看到如下图所示(目前点了还没有什么效果)
代码中获取配置信息,动态改变布局。接下来再编辑小组件,切换时间time/date时界面会发生响应的变化
struct WidgetConfigIntentEntryView : View {
var entry: Provider.Entry
var body: some View {
// 根据配置信息动态改变布局
if (entry.configuration.timeType == TimeTypeEnum.time) {
Text(entry.date, style: .time)
} else {
Text(entry.date, style: .date)
}
}
}
结语
本文讲解了实现一个简单的可配置小组件,不过数据都是静态配置,下一节讲解动态修改配置数据,这个在实际开发中也是比较重要的环节。