Xcode中NSSpeechRecognizer代理失效,配置权限后仍无法运行
Hey there, let's fix your NSSpeechRecognizer issue step by step. I've gone through your code and spotted several key problems that are preventing it from working correctly. Here's the corrected version of your code, followed by a breakdown of what was wrong and how to fix it:
import Cocoa class ViewController: NSViewController, NSSpeechRecognizerDelegate { // Use optional to avoid risky force unwrapping var speechRec: NSSpeechRecognizer? let commands = ["a","b","c","d","stop","go"] override func viewDidLoad() { super.viewDidLoad() // First check if speech recognition is available on the device guard NSSpeechRecognizer.isAvailable() else { print("Speech recognition isn't available on this device") return } // Initialize recognizer safely speechRec = NSSpeechRecognizer() speechRec?.commands = commands speechRec?.delegate = self // Explicitly set language to match your English commands (adjust if needed) speechRec?.setLanguage("en-US") // Keep listening restricted to app foreground (default behavior, but explicit is clearer) speechRec?.listensInForegroundOnly = true speechRec?.blocksOtherRecognizers = true print("Speech recognizer initialized and ready") } @IBAction func Listen(_ sender: Any) { guard let recognizer = speechRec else { print("Speech recognizer isn't initialized yet") return } recognizer.startListening() print("Listening now...") } @IBAction func Stop(_ sender: Any) { speechRec?.stopListening() print("Stopped Listening...") } // Corrected delegate method with proper string interpolation func speechRecognizer(_ sender: NSSpeechRecognizer, didRecognizeCommand command: String) { print("Recognized command: \(command)") switch command { case "a", "b", "c", "d", "stop", "go": print("You picked \(command)") default: print("Unrecognized command: \(command)") } } // Optional delegate method to debug recognition failures func speechRecognizer(_ sender: NSSpeechRecognizer, didNotRecognizeCommandWith error: Error?) { if let error = error { print("Recognition error: \(error.localizedDescription)") } else { print("No matching command recognized") } } }
Key Fixes & Improvements:
- Safe Initialization: Your original code used
NSSpeechRecognizer()!which forces unwrapping, but this can crash if speech recognition is unavailable. We now use an optional and check availability upfront withNSSpeechRecognizer.isAvailable(). - Fixed String Interpolation: You had
\\(command)in print statements — Swift only uses a single backslash for interpolation:\(command). - Explicit Language Setting: Adding
speechRec?.setLanguage("en-US")ensures the recognizer uses the correct language for your English commands, which is critical if your system default language isn't English. - Error Debugging Delegate: The added
didNotRecognizeCommandWithmethod helps you pinpoint why commands aren't being picked up (e.g., permission blocks, unclear audio). - Safety Guards: Guard clauses in the
Listenaction prevent crashes if the recognizer isn't properly initialized.
Permission Configuration Double-Check:
Even if you added the plist entries, confirm they're correctly set:
- In your
Info.plist, add these keys with clear, specific descriptions (the system requires these to show permission prompts):NSSpeechRecognitionUsageDescription: "We need speech recognition to process your voice commands"NSMicrophoneUsageDescription: "We need access to your microphone to listen for voice commands"
- After updating, clean your build folder (Shift + Command + K) and restart Xcode to ensure changes take effect.
Additional Troubleshooting Tips:
- Verify your microphone is working and not muted.
- Speak clearly at a normal volume when testing commands.
- If permission prompts don't appear, go to System Settings > Privacy & Security > Speech Recognition (and Microphone) to manually enable access for your app.
- Test with simple, distinct commands first to rule out recognition accuracy issues.
内容的提问来源于stack exchange,提问作者Shyamal Chandra




