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

Swift中基于Apple Intelligence的ShowInAppSearchResultsIntent Siri语音调用异常问题求助

Swift中基于Apple Intelligence的ShowInAppSearchResultsIntent Siri语音调用异常问题求助

看起来你在集成WWDC24推出的ShowInAppSearchResultsIntent和AppShortcutsProvider时遇到了真机与模拟器行为不一致的问题,尤其是真机上出现的Failed to generate TargetContentIdentifier for criteria报错,我来帮你梳理下核心问题和解决方案:

你的问题复盘

  • iOS 18模拟器:Siri能正常触发搜索关键词询问,执行perform方法并弹出alert,但仅为测试阶段的反馈
  • 真机环境:直接打开App,不触发Siri的关键词询问,控制台抛出Failed to generate TargetContentIdentifier for criteria错误

核心原因分析

ShowInAppSearchResultsIntent是Apple Intelligence推出的系统级搜索意图,真机环境对该意图的要求比模拟器更严格:系统需要意图返回可定位到App内搜索内容的TargetContentIdentifier,否则会判定意图不完整,直接跳过参数询问流程打开App。

具体解决方案

1. 为Intent添加TargetContentIdentifier返回

在perform方法中返回带有搜索标识的结果,满足系统对搜索意图的要求:

@MainActor
func perform() async throws -> some IntentResult {
    let searchString = criteria.term
    print("Searching for \(searchString)")
    msgWithSingleButton(message: "Searching for \(searchString)", title: "Siri", buttonTitle: "OK")
    
    // 生成TargetContentIdentifier,可根据实际搜索结果调整标识规则
    let contentIdentifier = TargetContentIdentifier(searchString)
    // 返回包含对话和标识的结果,同时让Siri播报反馈
    return .result(
        dialog: "Searching for \(searchString) in \(.applicationName)",
        targetContentIdentifier: contentIdentifier
    )
}

2. 优化AppShortcut短语的参数绑定

让Siri更精准地将用户语音中的搜索词绑定到criteria参数,减少流程异常:

static var appShortcuts: [AppShortcut] {
    AppShortcut(
        intent: CineverseSearchIntent(),
        phrases: [
            "search for \(.parameter(\.criteria)) using \(.applicationName)",
            "look up \(.parameter(\.criteria)) on \(.applicationName)"
        ],
        shortTitle: "Search Movie",
        systemImageName: "sparkles",
        openAppWhenRun: true // 明确执行时打开App
    )
}

3. 确保Intent满足系统搜索意图的配置

在CineverseSearchIntent中添加openAppWhenRun静态属性,明确意图行为:

@AssistantIntent(schema: .system.search)
struct CineverseSearchIntent: ShowInAppSearchResultsIntent {
    static var title: LocalizedStringResource = "Search in Cineverse for"
    static var searchScopes: [StringSearchScope] = [.general]
    // 明确执行意图时打开App
    static var openAppWhenRun: Bool { true }

    @Parameter(requestValueDialog: IntentDialog("What would you like to search for?"))
    var criteria: StringSearchCriteria
    
    // ... 其他方法不变
}

4. 修复后台唤起时的Alert展示问题

当Siri在后台唤起App时,直接通过UIApplication获取rootViewController可能失败,建议调整msgWithSingleButton方法,确保在App激活时展示:

//Alert
@MainActor
func msgWithSingleButton(message: String, title: String = "", buttonTitle : String){
    guard let scenes = UIApplication.shared.connectedScenes as? [UIWindowScene],
          let windowScene = scenes.first,
          let window = windowScene.windows.first else {
        print("Cannot present alert: App is not active")
        return
    }
    
    // 如果当前有presented VC,需要在最上层展示
    let topVC = window.rootViewController?.presentedViewController ?? window.rootViewController
    guard let topVC = topVC else {
        print("Cannot present alert: No root view controller")
        return
    }
    
    let alertView = UIAlertController(title: title, message: message, preferredStyle: .alert)
    alertView.addAction(UIAlertAction(title: buttonTitle, style: .default, handler: nil))
    topVC.present(alertView, animated: true)
}

5. 真机环境的必要设置

  • 确保真机已开启Siri与Apple Intelligence(设置 -> Siri与搜索)
  • 为你的App开启Siri权限(设置 -> Siri与搜索 -> 找到你的App -> 开启“用Siri唤醒”和“允许Siri建议”)
  • 重新安装App到真机,并通过Siri测试快捷短语(比如:"用Cineverse搜索复仇者联盟")

完整修改后的代码

import AppIntents
import Foundation
import UIKit

@AssistantIntent(schema: .system.search)
struct CineverseSearchIntent: ShowInAppSearchResultsIntent {
    static var title: LocalizedStringResource = "Search in Cineverse for"
    static var searchScopes: [StringSearchScope] = [.general]
    static var openAppWhenRun: Bool { true }
    
    @Parameter(requestValueDialog: IntentDialog("What would you like to search for?"))
    var criteria: StringSearchCriteria
    
    @MainActor
    func perform() async throws -> some IntentResult {
        let searchString = criteria.term
        print("Searching for \(searchString)")
        msgWithSingleButton(message: "Searching for \(searchString)", title: "Siri", buttonTitle: "OK")
        
        let contentIdentifier = TargetContentIdentifier(searchString)
        return .result(
            dialog: "Searching for \(searchString) in \(.applicationName)",
            targetContentIdentifier: contentIdentifier
        )
    }
}

class AppShortcuts: AppShortcutsProvider {
    static var appShortcuts: [AppShortcut] {
        AppShortcut(
            intent: CineverseSearchIntent(),
            phrases: [
                "search for \(.parameter(\.criteria)) using \(.applicationName)",
                "look up \(.parameter(\.criteria)) on \(.applicationName)"
            ],
            shortTitle: "Search Movie",
            systemImageName: "sparkles",
            openAppWhenRun: true
        )
    }
}

//Alert
@MainActor
func msgWithSingleButton(message: String, title: String = "", buttonTitle : String){
    guard let scenes = UIApplication.shared.connectedScenes as? [UIWindowScene],
          let windowScene = scenes.first,
          let window = windowScene.windows.first else {
        print("Cannot present alert: No active window scene")
        return
    }
    
    let topVC = window.rootViewController?.presentedViewController ?? window.rootViewController
    guard let topVC = topVC else {
        print("Cannot present alert: No root view controller")
        return
    }
    
    let alertView = UIAlertController(title: title, message: message, preferredStyle: .alert)
    alertView.addAction(UIAlertAction(title: buttonTitle, style: .default, handler: nil))
    topVC.present(alertView, animated: true)
}

最后测试建议

  1. 清理Xcode缓存,删除真机上的旧App
  2. 重新编译安装,首次打开App时授予Siri权限
  3. 唤起Siri,测试快捷短语,比如:"用Cineverse搜索钢铁侠"
  4. 检查控制台是否还有TargetContentIdentifier报错

备注:内容来源于stack exchange,提问作者Supriyo Dey

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 09:23:04