iOS14 WidgetKit:单个Widget能否配置两个动态Intent?
在iOS14 WidgetKit中实现单个Widget带两个搜索式动态输入项的方案
可行,但不能通过绑定两个独立的IntentConfiguration实现,因为单个Widget只能关联一个自定义Intent类型。正确的做法是将两个输入项整合到同一个CustomIntent中,具体步骤如下:
1. 合并自定义Intent定义
打开Intents.intentdefinition文件,创建一个新的自定义Intent(例如命名为DoubleSelectionIntent),添加两个参数:
- 第一个参数(如
firstSelection):类型选择你自定义的Selections实体,勾选「Supports Search」开启搜索功能 - 第二个参数(如
secondSelection):同样选择Selections实体并开启搜索支持
这样Widget的配置界面会自动生成两个带搜索栏的输入项。
2. 更新IntentHandler实现
在IntentHandler中,为合并后的Intent的两个参数分别实现选项提供方法:
class IntentHandler: INExtension, DoubleSelectionIntentHandling { // 为第一个输入项提供搜索选项 func provideFirstSelectionOptionsCollection(for intent: DoubleSelectionIntent, with completion: @escaping (INObjectCollection<Selections>?, Error?) -> Void) { // 构造你的选项数据,这里示例生成几个测试项 let options = [ Selections(identifier: "opt1", display: "选项1"), Selections(identifier: "opt2", display: "选项2"), Selections(identifier: "opt3", display: "选项3") ] completion(INObjectCollection(items: options), nil) } // 为第二个输入项提供搜索选项 func provideSecondSelectionOptionsCollection(for intent: DoubleSelectionIntent, with completion: @escaping (INObjectCollection<Selections>?, Error?) -> Void) { let options = [ Selections(identifier: "optA", display: "选项A"), Selections(identifier: "optB", display: "选项B"), Selections(identifier: "optC", display: "选项C") ] completion(INObjectCollection(items: options), nil) } // 可选:实现确认Intent的方法 func confirm(intent: DoubleSelectionIntent, completion: @escaping (DoubleSelectionIntentResponse) -> Void) { completion(DoubleSelectionIntentResponse(code: .success, userActivity: nil)) } }
3. 配置Widget结构体
将Widget的IntentConfiguration绑定到合并后的DoubleSelectionIntent:
struct MyWidget: Widget { let kind: String = "MyWidget" var body: some WidgetConfiguration { IntentConfiguration( kind: kind, intent: DoubleSelectionIntent.self, provider: WidgetTimelineProvider() ) { entry in MyWidgetEntryView(entry: entry) } .configurationDisplayName("双选择Widget") .description("支持两个搜索式输入项的Widget") .supportedFamilies([.systemSmall, .systemMedium]) } }
4. 在TimelineProvider中处理双参数
修改IntentTimelineProvider,指定泛型类型为DoubleSelectionIntent,并在方法中获取两个参数的值用于生成Timeline:
struct WidgetTimelineProvider: IntentTimelineProvider { typealias Intent = DoubleSelectionIntent typealias Entry = WidgetEntry func placeholder(in context: Context) -> WidgetEntry { WidgetEntry(date: Date(), firstChoice: nil, secondChoice: nil) } func getSnapshot(for configuration: DoubleSelectionIntent, in context: Context, completion: @escaping (WidgetEntry) -> Void) { let entry = WidgetEntry( date: Date(), firstChoice: configuration.firstSelection, secondChoice: configuration.secondSelection ) completion(entry) } func getTimeline(for configuration: DoubleSelectionIntent, in context: Context, completion: @escaping (Timeline<WidgetEntry>) -> Void) { // 根据两个选择的参数获取数据,生成时间线条目 let currentEntry = WidgetEntry( date: Date(), firstChoice: configuration.firstSelection, secondChoice: configuration.secondSelection ) let timeline = Timeline(entries: [currentEntry], policy: .atEnd) completion(timeline) } } // 对应的TimelineEntry结构体 struct WidgetEntry: TimelineEntry { let date: Date let firstChoice: Selections? let secondChoice: Selections? }
关键说明
WidgetKit不支持单个Widget绑定多个独立Intent,必须将多个输入项整合到同一个Intent中。通过这种方式,用户在添加Widget时,配置界面会依次显示两个带搜索栏的输入字段,分别对应你定义的两个参数,且各自的搜索选项由IntentHandler中对应的方法提供。
内容的提问来源于stack exchange,提问作者anoo_radha
相关产品推荐
相关产品推荐

