Fix speech authorization crash on device from dispatch queue assertion

Request authorization off main queue and marshal callback result back
via DispatchQueue.main.async. Check current status first to avoid
unnecessary system prompt if already authorized or denied.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-04-13 16:19:03 -05:00
parent 93ab7b3e16
commit a3807faf2d

View File

@@ -16,19 +16,29 @@ final class PronunciationService {
private var recognizerResolved = false private var recognizerResolved = false
func requestAuthorization() { func requestAuthorization() {
// SFSpeechRecognizer.requestAuthorization crashes on simulators
// without speech services. Check availability first.
guard SFSpeechRecognizer.self != nil else { return }
#if targetEnvironment(simulator) #if targetEnvironment(simulator)
print("[PronunciationService] skipping speech auth on simulator") print("[PronunciationService] skipping speech auth on simulator")
isAuthorized = false return
#else #else
print("[PronunciationService] requesting speech authorization...") // Check current status first to avoid unnecessary prompt
SFSpeechRecognizer.requestAuthorization { [weak self] status in let currentStatus = SFSpeechRecognizer.authorizationStatus()
print("[PronunciationService] authorization status: \(status.rawValue)") if currentStatus == .authorized {
Task { @MainActor in isAuthorized = true
self?.isAuthorized = (status == .authorized) return
}
if currentStatus == .denied || currentStatus == .restricted {
isAuthorized = false
return
}
// Only request if not determined yet do it on a background queue
// to avoid blocking main thread, then update state on main
DispatchQueue.global(qos: .userInitiated).async {
SFSpeechRecognizer.requestAuthorization { status in
DispatchQueue.main.async { [weak self] in
self?.isAuthorized = (status == .authorized)
print("[PronunciationService] authorization status: \(status.rawValue)")
}
} }
} }
#endif #endif