1. Intents Extension基础知识
1. 必需依赖Widget Extension
2. 用于给Widget Extension,提供编辑能力
3. 支持版本,iOS14+
2. Intents Extension实现流程
1. 创建target Intents Extension
2. 创建.intentdefinition文件
3. 在.intentdefinition文件中配置intent
4. 在Intents Extension target中遵循配置的intent协议
5. 结构体Widget,修改整合方式
5.1 修改provider遵循的协议
2.1. Intents Extension
1.1 File -> New -> target -> Intents Extension
到此,先放一边
2.2. .intentdefinition文件
2.1 Widget Extension的target下 command+n -> SiriKit Intent definition File
2.2 记住.intentdefinition文件需要关联两个target,Widget Extension target 和 Intents Extension target
到此,先放一边
2.3 .intentdefinition文件中配置intent
按照下图配置,完成后编译项目。系统会生成对应的类(SIntentIntent)与协议(SIntentIntentHanding)
2.4. 在Intents Extension target中遵循配置的intent协议
系统生成的IntentHandler文件中,让类IntentHandler遵循SIntentIntentHandling协议, 实现协议方法
ps: SIntentIntentHandling这个协议名,是因为创建的intent名是SIntent
import Intents
class IntentHandler: INExtension {
let animals: [Animal] = {
var anmls: [Animal] = []
for (index,value) in ["cat","dog","fish","bird"].enumerated() {
let anml = Animal(identifier: "\(index)", display: value)
anml.name = value
anml.subtitleString = "this is little cat"
anmls.append(anml)
}
return anmls
}()
override func handler(for intent: INIntent) -> Any {
return self
}
}
extension IntentHandler: SIntentIntentHandling {
func provideAnimalOptionsCollection(for intent: SIntentIntent, searchTerm: String?, with completion: @escaping (INObjectCollection<Animal>?, (any Error)?) -> Void) {
print(#line, searchTerm as Any)
var anmls = animals
if let search = searchTerm {
anmls = animals.filter { $0.displayString.lowercased().contains(search.lowercased()) }
}
completion(INObjectCollection(items: anmls), nil)
}
//初始化是,默认值
func defaultAnimal(for intent: ConfigIntent) -> Animal? {
animals.first
}
}
2.5. 结构体Widget,修改整合方式。修改Provider遵循协议
1. Provider遵循IntentTimeLineProvider协议,基础Widget遵循的是TimeLineProvider
2. 结构体Widget,整合方法改成IntentConfiguration, 基础Widget使用的是StaticConfiguration
struct Provider: IntentTimelineProvider {
typealias Intent = SIntentIntent
typealias Entry = SimpleEntry
func placeholder(in context: Context) -> Entry {
Entry(date: Date())
}
func getSnapshot(for configuration: Intent, in context: Context, completion: @escaping (Entry) -> Void) {
completion(Entry(date: Date()))
}
func getTimeline(for configuration: Intent, in context: Context, completion: @escaping (Timeline<Entry>) -> Void) {
print(#line,configuration)
let entry = Entry(date: Date())
let timeline = Timeline(entries: [entry], policy: .never)
completion(timeline)
}
}
struct TestWidget: Widget {
let kind: String = "intentWidget.com"
var body: some WidgetConfiguration {
IntentConfiguration(kind: kind, intent: SIntentIntent.self, provider: Provider()) { entry in
if #available(iOS 17.0, *) {
TestWidgetView(entry: entry)
.containerBackground(.fill.tertiary, for: .widget)
} else {
TestWidgetView(entry: entry)
.padding()
.background()
}
}
.configurationDisplayName("widget")
.description("This is intent widget")
.supportedFamilies([.systemSmall,.systemMedium,.systemLarge,.accessoryInline,.accessoryCircular,.accessoryRectangular])
}
}