iOS AppIntent参数如何设置自定义默认值?跨快捷复用方案
问题
我正在创建一组快捷指令,其中一个用于设置设备名称,另一个对已设置的设备执行操作。为此我创建了自定义AppIntent,其中一个参数为string类型,希望将其默认值设为之前存储在UserDefaults中的值,但尝试以下代码时:
struct AppIntentSetUp: AppIntent { @Parameter(title: "DeviceName", description: "The device name", default: deviceName, inputOptions: String.IntentInputOptions(capitalizationType: .words), requestValueDialog: IntentDialog("What is the device name?")) var device: String static var parameterSummary: some ParameterSummary { Summary("Select the device \(\.$device) ") } static var title: LocalizedStringResource { .init(stringLiteral: "AppIntentSetUp") } func perform() async throws -> some IntentResult { //do my action return .result(value: "") } } var deviceName: String? { UserDefaults(suiteName: "MyDeviceName")?.object(forKey: "MyDevice") as? String }
编译器报错:
Expect a compile-time constant literal
我理解默认值需要编译时常量,请问是否有方法为AppIntent参数设置自定义默认值?或有其他方式实现跨快捷指令复用参数值的目标?
解决方案
方法一:在perform方法中处理默认值逻辑
既然@Parameter的default参数只能用编译时常量,你可以把参数设为可选类型,然后在perform方法里判断如果参数为空,就从UserDefaults读取存储的值:
struct AppIntentSetUp: AppIntent { @Parameter(title: "DeviceName", description: "The device name", inputOptions: String.IntentInputOptions(capitalizationType: .words), requestValueDialog: IntentDialog("What is the device name?")) var device: String? // 改为可选类型 static var parameterSummary: some ParameterSummary { Summary("Select the device \(\.$device) ") } static var title: LocalizedStringResource { .init(stringLiteral: "AppIntentSetUp") } func perform() async throws -> some IntentResult { // 处理默认值:如果device为空,读取UserDefaults中的值 let targetDevice = device ?? UserDefaults(suiteName: "MyDeviceName")?.string(forKey: "MyDevice") ?? "" // 使用targetDevice执行操作 return .result(value: "") } }
方法二:使用DynamicOptionsProvider提供动态选项(适合需要让用户选择的场景)
如果希望用户能直接选择之前存储的设备名称,同时支持输入新名称,可以用DynamicOptionsProvider来动态生成选项列表:
struct AppIntentSetUp: AppIntent { @Parameter(title: "DeviceName", description: "The device name", inputOptions: String.IntentInputOptions(capitalizationType: .words), requestValueDialog: IntentDialog("What is the device name?"), optionsProvider: DeviceOptionsProvider()) var device: String static var parameterSummary: some ParameterSummary { Summary("Select the device \(\.$device) ") } static var title: LocalizedStringResource { .init(stringLiteral: "AppIntentSetUp") } func perform() async throws -> some IntentResult { // 保存或使用device值 UserDefaults(suiteName: "MyDeviceName")?.set(device, forKey: "MyDevice") return .result(value: "") } } // 自定义动态选项提供者 struct DeviceOptionsProvider: DynamicOptionsProvider { func results() async throws -> [String] { // 返回存储的设备名称作为选项,可添加其他默认选项 if let savedDevice = UserDefaults(suiteName: "MyDeviceName")?.string(forKey: "MyDevice") { return [savedDevice, "输入新设备名称"] } return ["输入新设备名称"] } }
方法三:跨快捷指令复用参数的其他思路
- 用
UserDefaults作为全局存储中心,所有需要复用参数的AppIntent都直接从这里读取和写入,无需依赖参数默认值。 - 如果是更复杂的场景,可以创建一个单例类来管理设备名称的存储和读取,封装
UserDefaults的操作,让各个AppIntent统一调用这个类的方法获取值。
内容的提问来源于stack exchange,提问作者Kashem
相关产品推荐
相关产品推荐

