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

iOS 16 Siri AppIntents按电源键激活无确认且弹窗不消失问题

问题描述

我开发了一款名为“SiriTest”的简易清单应用:

  • 通过语音指令“嘿 Siri,添加到SiriTest”可正常添加条目:Siri会提示说出条目内容,添加完成后会进行语音确认并自动关闭对话界面。
  • 但通过长按电源键激活Siri时,虽然条目能成功添加到清单中,Siri对话界面却会停留在“One moment....”或“One sec...”状态,无语音确认,直到点击屏幕其他区域才会消失。

请问如何实现长按电源键激活Siri时,让Siri完成语音确认并自动关闭对话界面?

附相关代码:

意图实现代码

import AppIntents
import SwiftUI

@available(iOS 16, *)
struct AddItemIntent: AppIntent {

    static var title: LocalizedStringResource = "Add item"
    
    @Parameter(title: "Item name")
    var itemName: String
    
    @MainActor
    func perform() async throws -> some ProvidesDialog {
        
        DispatchQueue.main.async {
            ItemModel.shared.addItem(itemName: itemName)
        }
            return .result(
                dialog: "Added to your list."
            )
    }
}

@available(iOS 16.0, *)
struct ListShortcuts: AppShortcutsProvider {
    static var appShortcuts: [AppShortcut] {
        AppShortcut(
            intent: AddItemIntent(),
            phrases: [
                "Add item to \(.applicationName)",
                "Add to \(.applicationName)",
            ]
        )
    }
}

数据模型代码

import Foundation

class ItemModel: ObservableObject {
    static let shared: ItemModel = ItemModel()
    
    @Published var list: [String] = []
    
    init() {
        dummyItems()
    }
    
    func addItem(itemName: String) {
        list.append(itemName)
    }
    
    func dummyItems() {
        list.append(contentsOf: ["One", "Two", "Three"])
    }
}

视图及应用入口代码

import SwiftUI

struct ContentView: View {
    
    @EnvironmentObject var itemModel: ItemModel
    
    var body: some View {
        List(itemModel.list, id: \.self) {item in
            Text(item)
        }
    }
}
import SwiftUI

@main
struct SiriTestApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(ItemModel.shared)
        }
    }
}
解决方案

问题出在perform方法中多余的DispatchQueue.main.async调度。因为@MainActor已经保证该方法在主线程执行,手动嵌套主线程异步调用会导致Siri的回调时序混乱,进而无法正常触发语音确认和界面关闭。

修改AddItemIntent的perform方法,移除不必要的主线程包裹:

@available(iOS 16, *)
struct AddItemIntent: AppIntent {

    static var title: LocalizedStringResource = "Add item"
    
    @Parameter(title: "Item name")
    var itemName: String
    
    @MainActor
    func perform() async throws -> some ProvidesDialog {
        // 直接调用addItem,无需额外主线程调度
        ItemModel.shared.addItem(itemName: itemName)
        return .result(
            dialog: "Added to your list."
        )
    }
}

原因说明

  1. @MainActor修饰的perform方法本身就在主线程执行,ItemModel的addItem是简单的数组追加操作,完全可以直接在当前主线程上下文完成。
  2. 额外的DispatchQueue.main.async会把添加操作放到主线程的异步队列中,导致Siri在等待意图完成时,无法及时收到操作完成的信号,从而停留在加载状态。
  3. 移除该调度后,意图操作会同步完成,Siri能立即触发语音确认并自动关闭对话界面,无论哪种激活方式(语音唤醒/长按电源键)都会保持一致的行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 01:20:21