Using Dictation - iOS 6 - DidStart?

2019-03-28 09:40发布

问题:

How to respond to starting dictation?


Known ways of responding to dictation:

  • dictationRecordingDidEnd - respond to the completion of the recognition of a dictated phrase.

  • dictationRecognitionFailed - respond to failed dictation recognition.


Reference: UITextInput Protocol Reference

Starting in iOS 5.1, when the user chooses dictation input on a supported device, the system automatically inserts recognized phrases into the current text view. Methods in the UITextInput protocol allow your app to respond to the completion of dictation, as described in “Using Dictation.” You can use an object of the UIDictationPhrase class to obtain a string representing a phrase a user has dictated. In the case of ambiguous dictation results, a dictation phrase object provides an array containing alternative strings.

http://developer.apple.com/library/ios/#documentation/uikit/reference/UITextInput_Protocol/Reference/Reference.html

回答1:

As far as I can tell, there's no public API for detecting when dictation has started.

If you really want to do it, and you want to be in the App Store, you can probably get away with the following approach, but it is totally unsupported, it might get you rejected anyway, and it is likely to break in a future version of iOS.

The text system posts some undocumented notifications after changing to or from the dictation “keyboard”. Two of them are posted both on a change to it and a change from it, with these names:

  • UIKeyboardCandidateCorrectionDidChangeNotification
  • UIKeyboardLayoutDidChangedNotification

Note that the second one has a strange verb conjugation. That is not a typo. (Well, it's not my typo.)

These notices are also posted at other times, so you can't just observe them and assume the dictation state has changed. You'll need to do more checking when you receive the notification. So, add yourself as an observer of one of those notifications. The first one seems less likely to go away or be renamed in the future.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [[NSNotificationCenter defaultCenter] addObserver:self
        selector:@selector(checkForDictationKeyboard:)
        name:@"UIKeyboardCandidateCorrectionDidChangeNotification"
        object:nil];
    ...

When you receive the notification, you'll want to see whether the dictation view is showing:

- (void)checkForDictationKeyboard:(NSNotification *)note {
    if ([self isShowingDictationView]) {
        NSLog(@"showing dictation view");
    } else {
        NSLog(@"not showing dictation view");
    }
}

To see whether it's showing, check each window except your own application window. Normally, the only other window is the text system's window.

- (BOOL)isShowingDictationView {
    for (UIWindow *window in [UIApplication sharedApplication].windows) {
        if (window == self.window)
            continue;
        if (containsDictationView(window))
            return YES;
    }
    return NO;
}

Recursively walk the view hierarchy checking for a view whose class name contains the string “DictationView”. The actual class name is UIDictationView but by not using the whole name you're less likely to be rejected from the App Store.

static BOOL containsDictationView(UIView *view) {
    if (strstr(class_getName(view.class), "DictationView") != NULL)
        return YES;
    for (UIView *subview in view.subviews) {
        if (containsDictationView(subview))
            return YES;
    }
    return NO;
}


回答2:

Although this question is answered, I still want to add my solution and wish to be helpful to someone else.

When you tap on the MIC button on the keyboard, primaryLanguage will change to dictation. You can detect that like this:

[[NSNotificationCenter defaultCenter] 
         addObserver:self 
            selector:@selector(handleCurrentInputModeDidChange:)
                name:UITextInputCurrentInputModeDidChangeNotification 
              object:nil];

- (void) handleCurrentInputModeDidChange:(NSNotification *)notification
{
    NSString *primaryLanguage = [UITextInputMode currentInputMode].primaryLanguage;

    NSLog(@"current primaryLanguage is: %@", primaryLanguage);
}

UPDATE: Just as what @user1686700 said, currentInputMode already been deprecated. This isn't a solution any more.



回答3:

Please note - UITextInputMode's currentInputMode is deprecated as of iOS7. We may just have to wait until Apple decides to publish the dictation API so we can make the calls that make sense as per our intentions.