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

自定义AppEntity的Siri Shortcut AppIntent重复请求输入问题求助

Siri快捷指令自定义AppEntity异常问题解决

我用SwiftUI开发应用,想实现自定义Siri快捷指令,为此创建了专属的BookEntity,但遇到问题:当选择建议列表里除首个之外的条目时,Siri会持续要求输入。我尝试复刻WWDC的示例代码,问题依然存在,相关代码如下:

struct BookEntity: AppEntity, Identifiable {
    var id: UUID
    
    var title : String

    var displayRepresentation: DisplayRepresentation {
        DisplayRepresentation(stringLiteral: "\(title)")
    }

    static var typeDisplayRepresentation: TypeDisplayRepresentation = "Book"

    static var defaultQuery = BookQuery()
}

struct BookQuery: EntityStringQuery {
    func entities(for identifiers: [UUID]) async throws -> [BookEntity] {
        let entries = try await suggestedEntities()
        return identifiers.compactMap { identifier in
            entries.filter{$0.id == identifier}.first
        }
    }

    func suggestedEntities() async throws -> [BookEntity] {
        let titles = ["Hallo","Du","Schöne","Welt"]
        return titles.map{BookEntity(id: UUID(), title: $0)}
    }

    func entities(matching string: String) async throws -> [BookEntity] {
        return try await suggestedEntities()
    }
}

struct OpenBook: AppIntent {
    @Parameter(title: "Book")
    var book: BookEntity

    static var title: LocalizedStringResource = "Open Book"

    static var openAppWhenRun = true

    @MainActor
    func perform() async throws -> some IntentResult {
        guard try await $book.requestConfirmation(for: book, dialog: "Are you sure you want to clear read state for \(book)?") else {
            return .result()
        }
        return .result()
    }

    static var parameterSummary: some ParameterSummary {
        Summary("Open \(\.$book)")
    }
  
    init() {}

    init(book: BookEntity) {
        self.book = book
    }
}

问题根源

你的BookQuery中,每次调用suggestedEntities()都会生成全新的UUID,导致entities(for identifiers:)方法里,传入的identifiers无法匹配到任何实体——因为每次生成的BookEntity都是新ID,Siri找不到对应实体,就会反复请求用户确认。

修正后的代码

把建议实体的UUID固定下来,或者缓存实体列表,确保每次查询时ID一致:

struct BookEntity: AppEntity, Identifiable {
    var id: UUID
    var title : String

    var displayRepresentation: DisplayRepresentation {
        DisplayRepresentation(stringLiteral: "\(title)")
    }

    static var typeDisplayRepresentation: TypeDisplayRepresentation = "Book"
    static var defaultQuery = BookQuery()
    
    // 预定义固定ID的书籍实体
    static let sampleBooks: [BookEntity] = [
        BookEntity(id: UUID(uuidString: "00000000-0000-0000-0000-000000000001")!, title: "Hallo"),
        BookEntity(id: UUID(uuidString: "00000000-0000-0000-0000-000000000002")!, title: "Du"),
        BookEntity(id: UUID(uuidString: "00000000-0000-0000-0000-000000000003")!, title: "Schöne"),
        BookEntity(id: UUID(uuidString: "00000000-0000-0000-0000-000000000004")!, title: "Welt")
    ]
}

struct BookQuery: EntityStringQuery {
    func entities(for identifiers: [UUID]) async throws -> [BookEntity] {
        // 直接从预定义样本中匹配ID
        return BookEntity.sampleBooks.filter { identifiers.contains($0.id) }
    }

    func suggestedEntities() async throws -> [BookEntity] {
        return BookEntity.sampleBooks
    }

    func entities(matching string: String) async throws -> [BookEntity] {
        // 根据输入字符串过滤实体(示例保留全匹配逻辑)
        return BookEntity.sampleBooks.filter { $0.title.localizedCaseInsensitiveContains(string) }
    }
}

struct OpenBook: AppIntent {
    @Parameter(title: "Book")
    var book: BookEntity

    static var title: LocalizedStringResource = "打开书籍"
    static var openAppWhenRun = true

    @MainActor
    func perform() async throws -> some IntentResult {
        guard try await $book.requestConfirmation(for: book, dialog: "确定要清除《\(book.title)》的阅读状态吗?") else {
            return .result()
        }
        // 此处添加实际打开书籍的业务逻辑
        return .result()
    }

    static var parameterSummary: some ParameterSummary {
        Summary("打开 \(\.$book)")
    }
  
    init() {}
    init(book: BookEntity) {
        self.book = book
    }
}

额外注意事项

  • 确保Info.plist中配置了Siri权限描述(NSSiriUsageDescription)
  • 测试前重启Siri和应用,避免缓存导致的异常
  • 如果实体从网络/本地数据库获取,需保证每次查询返回的实体ID一致,不要动态生成新ID

内容的提问来源于stack exchange,提问作者Foaly333

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 02:20:00