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." ) } }
原因说明
@MainActor修饰的perform方法本身就在主线程执行,ItemModel的addItem是简单的数组追加操作,完全可以直接在当前主线程上下文完成。- 额外的
DispatchQueue.main.async会把添加操作放到主线程的异步队列中,导致Siri在等待意图完成时,无法及时收到操作完成的信号,从而停留在加载状态。 - 移除该调度后,意图操作会同步完成,Siri能立即触发语音确认并自动关闭对话界面,无论哪种激活方式(语音唤醒/长按电源键)都会保持一致的行为。
内容的提问来源于stack exchange,提问作者dredzed
相关产品推荐
相关产品推荐

