如何在App Intents框架中使用解析器API(如DoubleFromStringResolver)将Siri输入的字符串转为Double类型参数?
嗨,我完全明白你在App Intents里遇到的Siri识别Double参数的困扰——之前做健康类Intent的时候我也踩过类似的坑!下面我来一步步帮你用DoubleFromStringResolver搞定这个问题,同时优化你的参数结构,让Siri的数值识别准确率大大提升。
问题根源:为什么原来的Double参数Siri识别不好?
默认情况下,App Intents对Double类型参数没有内置的自然语言解析逻辑,Siri不知道怎么把你说的“三点五个单位”这种语音输入转成Double值。而DoubleFromStringResolver就是专门用来解决这个问题的——它内置了处理自然语言数值的逻辑,能自动提取语音中的数值部分转成Double。
解决方案:简化参数+绑定DoubleFromStringResolver
首先,你不需要同时保留枚举参数和Double可选参数(这反而会让Siri的参数匹配逻辑混乱),直接用一个绑定了解析器的Double参数就能搞定所有场景:Siri能识别的话直接转成数值,识别不了的话会自动触发请求用户输入的对话框。
修改后的完整代码示例
import AppIntents struct AddInsulin: AppIntent { static var title: LocalizedStringResource = "Record Insulin Injection" static var description: LocalizedStringResource = "Ask the system to record insulin units for IOB calculation." // 核心修改:绑定DoubleFromStringResolver,参数设为非可选(解析器会处理识别失败的情况) @Parameter( title: "Insulin Units", description: "How many insulin units?", requestValueDialog: "How much insulin?", resolver: DoubleFromStringResolver() ) var insulinUnits: Double static var parameterSummary: some ParameterSummary { Summary("Record \(\.$insulinUnits) units of insulin") } @MainActor func perform() async throws -> some IntentResult & ProvidesDialog & ShowsSnippetView { // 校验数值有效性 guard insulinUnits > 0 else { throw $insulinUnits.needsValueError("Please enter a positive number of insulin units.") } // 这里执行你的IOB计算逻辑,比如保存记录到数据库 // 示例:let record = InsulinRecord(units: insulinUnits, date: Date()) // CoreDataManager.shared.save(record) // 返回结果和对话 let dialogMessage = "Recorded \(insulinUnits) units of insulin." return .result(dialog: dialogMessage) { // 这里返回你要展示的SnippetView Text("Insulin Recorded: \(insulinUnits) units") .padding() } } }
关键细节解释
DoubleFromStringResolver()的作用
这个解析器会自动处理:- 整数输入(比如Siri听到“5 units”转成5.0)
- 小数输入(“three point five units”转成3.5)
- 本地化数值格式(比如欧洲地区的“3,5”会自动转成3.5)
- 自然语言表述的数值(比如“half a unit”转成0.5)
简化参数结构的好处
原来的两个同名参数(insulinUnitsEnum和unitsDouble)会让Siri的参数匹配逻辑混乱,合并成一个带Resolver的参数后,Siri会直接用解析器处理所有输入场景,不需要你自己做分支判断。参数的可选性处理
绑定Resolver后,你可以把参数设为非可选类型:如果Siri识别失败,解析器会自动触发requestValueDialog,弹出对话框让用户手动输入数值,所以你在perform方法里可以直接使用确定的Double值,不需要处理nil情况。数值有效性校验
在perform里加一个guard语句校验数值大于0,避免无效的记录,同时抛出的错误会引导用户输入正确的数值。
额外优化建议
如果你需要给快捷方式提供固定的常用数值选项(比如1、2、5单位),可以给DoubleFromStringResolver加上allowedValues,比如:
resolver: DoubleFromStringResolver(allowedValues: [1.0, 2.0, 3.0, 5.0, 10.0])
这样在快捷方式编辑器里会显示这些固定选项,同时Siri仍然能识别不在列表里的自定义数值(如果用户说“4.5 units”,解析器还是会正确转成4.5)。
内容来源于stack exchange

