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
func requestAuthorization() {
// SFSpeechRecognizer.requestAuthorization crashes on simulators
// without speech services. Check availability first.
guard SFSpeechRecognizer.self != nil else { return }
#if targetEnvironment(simulator)
print("[PronunciationService] skipping speech auth on simulator")
isAuthorized = false
return
#else
print("[PronunciationService] requesting speech authorization...")
SFSpeechRecognizer.requestAuthorization { [weak self] status in
print("[PronunciationService] authorization status: \(status.rawValue)")
Task { @MainActor in
self?.isAuthorized = (status == .authorized)
// Check current status first to avoid unnecessary prompt
let currentStatus = SFSpeechRecognizer.authorizationStatus()
if currentStatus == .authorized {
isAuthorized = true
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