按钮触发UIAccessibility公告时为何有时无法朗读?
问题原因分析
这是VoiceOver的语音队列状态管理机制导致的行为,核心在于.accessibilitySpeechQueueAnnouncement属性的工作逻辑与VoiceOver的空闲状态判定:
1. .accessibilitySpeechQueueAnnouncement: true的作用
该属性会将你提交的公告加入VoiceOver的语音等待队列,而非打断当前正在朗读的内容。只有当队列处于「活跃状态」(即有正在朗读的内容)时,新的队列任务才会被正常排入并执行;但当队列刚完成朗读进入「空闲静默状态」时,VoiceOver会暂时忽略新的队列型公告——它默认用户可能正在准备下一个操作,避免不必要的语音打扰。
2. 两种场景的具体逻辑
- 场景2(按钮信息未读完时点击):此时VoiceOver的语音队列处于活跃状态,你提交的队列型公告会被正常追加到队列末尾,等按钮的无障碍信息读完后,自动继续朗读新公告。
- 场景1(按钮信息读完后点击):按钮的朗读完成后,队列进入空闲状态,VoiceOver会进入短暂的静默等待期。此时提交队列型公告,VoiceOver会判定这是无前置活跃任务的冗余队列请求,直接跳过不执行。
3. 设为false时的行为解释
当.accessibilitySpeechQueueAnnouncement设为false时,公告会以「打断型」模式提交:
- 场景2中,按钮的无障碍朗读是系统默认的高优先级语音,用户提交的打断型公告无法抢占优先级,所以被拦截;
- 场景1中,队列处于空闲状态,没有正在朗读的内容可供打断,自然也不会触发公告。
可行的解决方案
如果你需要在按钮朗读完成后点击也能触发公告,可以尝试以下两种方式:
方式1:延迟提交打断型公告
通过短暂延迟,避开VoiceOver的静默等待期,再提交打断型公告:
struct ContentView: View { var body: some View { VStack(spacing: 20) { Text("Test accessibility") .font(.largeTitle) Spacer() Button { DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { let message = "Test accessibility announcement" UIAccessibility.post(notification: .announcement, argument: message) } } label: { Text("Test accessibility button") } Spacer() } } }
方式2:使用SwiftUI专属的accessibilityAnnouncement修饰符
让系统自动处理公告的触发时机,无需手动管理队列:
struct ContentView: View { @State private var announcementText: String? = nil var body: some View { VStack(spacing: 20) { Text("Test accessibility") .font(.largeTitle) Spacer() Button { announcementText = "Test accessibility announcement" } label: { Text("Test accessibility button") } .accessibilityAnnouncement($announcementText) Spacer() } } }
内容的提问来源于stack exchange,提问作者rai212
相关产品推荐
相关产品推荐

