How to detect if voice dictation was used for UITextField? Or microphone button was tapped on keyboard. Is there any way to do that?
With keyboard dictation on iPhone, you can dictate text anywhere you can type it. On supported models, general text dictation (for example, composing messages and notes) can be processed on your device in many languages, and no internet connection is required. (Dictation in a search field is processed on a server.)
Apple also offers advanced commands for creating custom ones. Apple Dictation accuracy: On the 207-word test, 20 words were inaccurate, but note that I was using a borrowed MacBook Pro to perform the test, so it was the first time the Siri speech-recognition engine had heard my voice.
Hold down the iPhone's Home button (or say “Hey Siri” to wake up the software), say “Make a new note,” and then speak your thoughts — reciting the punctuation like “period” or “comma” aloud. The resulting note can be emailed, copied, pasted or shared with a compatible text app.
UITextField conforms to UITextInput Protocol ( under the section Using Dictation are methods of interest). In this protocol is a method dictationRecordingDidEnd that you can override.
One way is to subclass UITextField and implement the above mentioned method and any others of interest from the UITextInput protocol.
example subclass .h
#import <UIKit/UIKit.h>
@interface BWDictationTextField : UITextField
@end
.m
#import "BWDictationTextField.h"
@implementation BWDictationTextField
- (void)dictationRecordingDidEnd {
NSLog(@"%s", __PRETTY_FUNCTION__);
}// done is pressed by user after dictation
@end
Unfortunately there is no documented way to detect the actual tap of the microphone button ( dictation did start ).
A textfield will report changes when the text input changes including when dictation starts and stops. We can listen for this notification and report when dictation starts and stops.
Here is a Swift subclass using this technique.
protocol DictationAwareTextFieldDelegate: class {
func dictationDidEnd(_ textField: DictationAwareTextField)
func dictationDidFail(_ textField: DictationAwareTextField)
func dictationDidStart(_ textField: DictationAwareTextField)
}
class DictationAwareTextField: UITextField {
public weak var dictationDelegate: DictationAwareTextFieldDelegate?
private var lastInputMode: String?
private(set) var isDictationRunning: Bool = false
override func dictationRecordingDidEnd() {
isDictationRunning = false
dictationDelegate?.dictationDidEnd(self)
}
override func dictationRecognitionFailed() {
isDictationRunning = false
dictationDelegate?.dictationDidEnd(self)
}
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
private func commonInit() {
NotificationCenter.default.addObserver(self, selector: #selector(textInputCurrentInputModeDidChange), name: .UITextInputCurrentInputModeDidChange, object: nil)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
@objc func textInputCurrentInputModeDidChange(notification: Notification) {
guard let inputMode = textInputMode?.primaryLanguage else {
return
}
if inputMode == "dictation" && lastInputMode != inputMode {
isDictationRunning = true
dictationDelegate?.dictationDidStart(self)
}
lastInputMode = inputMode
}
}
As this class listens for a notification, the notification will be called many times if there is many DictationAwareTextFields. If this is a problem you must move the notification observing code out of the textField into a higher class like the view controller.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With