You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 05:37:06