iOS17迁移AppIntents:如何将选中国家参数传递给城市实体查询?
iOS 17 AppIntents 动态参数选项迁移方案
针对你从 SiriKit Intents 迁移到 AppIntents 时遇到的「根据已选国家动态生成城市选项」问题,且需兼容 iOS 16-17、不修改 Intent 参数结构的需求,可通过以下方案实现:
核心思路
利用 iOS 17 新增的 DynamicOptionsProvider 协议,直接在 Intent 内根据已选的 Country 参数动态返回 City 选项,无需修改原有参数结构,同时复用原有城市查询逻辑。
代码修改步骤
1. 让 MyIntent 实现 DynamicOptionsProvider
在原有 Intent 代码基础上添加协议实现,专门处理 City 参数的动态选项生成:
struct MyIntent: AppIntent, WidgetConfigurationIntent, CustomIntentMigratedAppIntent, DynamicOptionsProvider { static let intentClassName = "MyIntent" static var title: LocalizedStringResource = "Do Something" static var description = IntentDescription("Description of Do Something") @Parameter(title: "Country") var country: CountryAppEntity? @Parameter(title: "City") var city: CityAppEntity? // MARK: - 动态生成城市选项(仅 iOS 17+ 生效) @available(iOS 17.0, watchOS 10.0, macOS 14.0, tvOS 17.0, *) func dynamicOptions(for parameter: Parameter<CityAppEntity>, in context: DynamicOptionsContext) async throws -> [CityAppEntity] { // 获取用户当前选中的国家(优先取intent已绑定值,再从上下文补取) let selectedCountry = country ?? try? context.value(for: \.$country) // 调用统一的城市查询逻辑 return await CityAppEntity.retrieveCities(country: selectedCountry) } }
2. 重构 CityAppEntity 的查询逻辑
将原 CityAppEntityQuery 中的 retrieveCities 改为静态方法,让 Intent 和 Query 复用同一套逻辑:
struct CityAppEntity: AppEntity { static var typeDisplayRepresentation = TypeDisplayRepresentation(name: "City") struct CityAppEntityQuery: EntityQuery { func entities(for identifiers: [CityAppEntity.ID]) async throws -> [CityAppEntity] { // 根据ID过滤城市,如需按国家可扩展逻辑 return await retrieveCities(country: nil).filter { identifiers.contains($0.id) } } func suggestedEntities() async throws -> [CityAppEntity] { // 默认返回所有城市(iOS 17+ 会被dynamicOptions覆盖) return await retrieveCities(country: nil) } } static var defaultQuery = CityAppEntityQuery() var id: String var displayString: String var displayRepresentation: DisplayRepresentation { DisplayRepresentation(title: "\(displayString)") } init(id: String, displayString: String) { self.id = id self.displayString = displayString } // 改为静态方法,供Intent和Query复用 static func retrieveCities(country: CountryAppEntity?) async -> [CityAppEntity] { // 原有根据国家获取城市的业务逻辑 // ... } }
兼容性说明
- iOS 17+:通过
DynamicOptionsProvider实现动态参数联动,完全符合 AppIntents 新特性。 - iOS 16:依赖
CustomIntentMigratedAppIntent自动迁移原有 SiriKit IntentHandler 逻辑,无需额外修改即可保持原有功能。
内容的提问来源于stack exchange,提问作者optz
相关产品推荐
相关产品推荐

