BergP
BergP

Reputation: 3545

ios: how to detect if voice dictation was used for UITextField? Or microphone button was tapped on keyboard

How to detect if voice dictation was used for UITextField? Or microphone button was tapped on keyboard. Is there any way to do that?

enter image description here

Upvotes: 5

Views: 5416

Answers (2)

David Rees
David Rees

Reputation: 7332

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.

Upvotes: 3

Bamsworld
Bamsworld

Reputation: 5680

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 ).

Upvotes: 7

Related Questions