如何在SwiftUI中判断VoiceOver等辅助技术是否启用?
在SwiftUI中检测辅助技术(如VoiceOver)是否启用
直接调用UIKit的UIAccessibility API在SwiftUI里完全可行,但如果想要更贴合SwiftUI的响应式风格,推荐以下两种实现方式:
方式一:自定义@Environment变量(推荐)
通过自定义环境键,可以把辅助技术状态转化为SwiftUI环境变量,在视图层级中轻松访问,且状态变化时视图会自动更新。
1. 定义环境键
import SwiftUI import UIKit private struct VoiceOverEnabledKey: EnvironmentKey { static let defaultValue: Bool = UIAccessibility.isVoiceOverRunning } extension EnvironmentValues { var isVoiceOverEnabled: Bool { get { self[VoiceOverEnabledKey.self] } set { self[VoiceOverEnabledKey.self] = newValue } } }
2. 监听状态变化并同步到环境
在App入口或根视图中添加监听,实时更新状态:
@main struct YourApp: App { @State private var isVoiceOverEnabled = UIAccessibility.isVoiceOverRunning var body: some Scene { WindowGroup { ContentView() .environment(\.isVoiceOverEnabled, isVoiceOverEnabled) .onAppear { NotificationCenter.default.addObserver( forName: UIAccessibility.voiceOverStatusDidChangeNotification, object: nil, queue: .main ) { _ in isVoiceOverEnabled = UIAccessibility.isVoiceOverRunning } } } } }
3. 在视图中使用
struct ContentView: View { @Environment(\.isVoiceOverEnabled) private var isVoiceOverEnabled var body: some View { Text(isVoiceOverEnabled ? "VoiceOver已启用" : "VoiceOver未启用") } }
方式二:用ObservableObject管理状态
如果需要在多视图或ViewModel间共享状态,可以用ObservableObject封装:
import SwiftUI import UIKit class AccessibilityStatusManager: ObservableObject { @Published var isVoiceOverEnabled = UIAccessibility.isVoiceOverRunning init() { NotificationCenter.default.addObserver( forName: UIAccessibility.voiceOverStatusDidChangeNotification, object: nil, queue: .main ) { [weak self] _ in self?.isVoiceOverEnabled = UIAccessibility.isVoiceOverRunning } } } // 视图中调用示例 struct ContentView: View { @StateObject private var accessibilityManager = AccessibilityStatusManager() var body: some View { Text(accessibilityManager.isVoiceOverEnabled ? "VoiceOver已启用" : "VoiceOver未启用") } }
补充说明
- 针对Switch Control、Zoom等其他辅助技术,可复用类似逻辑:监听对应通知(如
UIAccessibility.switchControlStatusDidChangeNotification),调用UIAccessibility.isSwitchControlRunning等属性获取状态。 - 直接使用UIKit的
UIAccessibilityAPI本身并无问题,上述方案只是将其适配为SwiftUI的响应式风格,让状态变化自动驱动视图更新。
内容的提问来源于stack exchange,提问作者Jacob Jidell
相关产品推荐
相关产品推荐

