在 iOS 8 上使用私有语音识别框架

Work with private Speech Recognition Frameworks on iOS 8

我需要为个人项目的应用程序添加语音识别。

我需要 iOS built-in 语音识别框架,因为它快速、准确,还可以识别您的联系人姓名和其他有关您自己的信息。

到目前为止,我想我已经找到了包含 headers 的框架,用于 iOS 8 上的语音识别: SAObjects.framework 我得到了 Github 的 headers 并在我的 Xcode 项目中成功添加了它们。 目前我试过的 headers 是这些:

<SAObjects/SASRecognition.h>
<SAObjects/SASStartSpeechDictation.h>
<SAObjects/SASSpeechRecognized.h>

但是,我不确定如何与他们合作。例如,有两种可能的方法可以触发语音识别:

SASStartSpeechDictation *object1 = [SASStartSpeechDictation startSpeechDictation];

SASSpeechRecognized *object2 = [SASSpeechRecognized speechRecognized];

不过,当我调试它时,我在这些 objects 中找不到任何字符串。所以,显然出了点问题。 也许我需要设置一个通知观察者?

另一个解决方案可能是开始听写(通过键盘) 到隐藏的文本字段(不显示键盘)。 就像越狱设备的 Activator 操作一样,如果您熟悉的话。 但是没找到可以启动Keyboard听写的方法,或者Activator动作源码找找看。

也许有人试验过这些东西可以给我一些帮助?

如果您需要有关此问题的更多信息,请告诉我:)

非常感谢!

所以,我设法自己找到了答案。我幸运地找到了一个包含一些有用代码的 Github 仓库:https://github.com/erica/useful-things

我找到的代码在appstore unsafepack/DictationHelper目录下。此代码有助于使用 UIDictationController 并启动和停止听写,并获取文本值。 当然,没有任何文本字段...

重要提示:为了让它工作,你需要有 headers UIKit 框架,link 目标框架和在项目中导入它们!

但是,我稍微修改了代码,因为示例代码只能在特定时间段内使用。我需要按一个按钮停止说话。 这是修改后的代码,供以后有兴趣的人参考:

DicationHelper.h:

/*

 Erica Sadun, http://ericasadun.com

 NOT APP STORE SAFE BUT HANDY
 Siri-ready devices only. Will not work in simulator.

 Example:

 [SpeechHelper speakModalString:@"Please say something"];
 [[DictationHelper sharedInstance] dictateWithDuration:5.0f completion:^(NSString *dictationString) {
 if (dictationString)
 NSLog(@"You said:'%@'", dictationString);
 else
 NSLog(@"No response");}];

 //-> OR: (My modification)


 [SpeechHelper speakModalString:@"Please say something"];
 [[DictationHelper sharedInstance] startDictation:0 completion:^(NSString *dictationString) {
 if (dictationString)
 NSLog(@"You said:'%@'", dictationString);
 else
 NSLog(@"No response");}];

 // Then you need to call this to stop the Dictation: [[DictationHelper sharedInstance] stopDictation]

 */

#import <UIKit/UIKit.h>
//#import <Foundation/Foundation.h>

extern NSString *const DictationStringResults;

typedef void (^DictationBlock)(NSString *dictationString);

@interface DictationHelper : NSObject
+ (instancetype) sharedInstance;
- (void) dictateWithDuration: (CGFloat) duration;
- (void) dictateWithDuration: (CGFloat) duration completion:(DictationBlock) completionBlock;

-(void) startDictation:(CGFloat) whatever completion:(DictationBlock) completionBlock;
-(void) stopDictationWithFallback;

@property (nonatomic, readonly) BOOL inUse;
@end

DictationHelper.m

/*

 Erica Sadun, http://ericasadun.com

 NOT APP STORE SAFE BUT HANDY
 Siri-ready devices only. Will not work in simulator.

 */


#import "DictationHelper.h"
#define MAKELIVE(_CLASSNAME_)   Class _CLASSNAME_ = NSClassFromString((NSString *)CFSTR(#_CLASSNAME_));

NSString *const DictationStringResults = @"Dictation String Results";

static DictationHelper *sharedInstance = nil;

@class UIDictationController;

@interface UIDictationController
+ (UIDictationController *) sharedInstance;
- (void) startDictation;
- (void) stopDictation;
- (void) preheatIfNecessary;
@end;

@interface DictationHelper () <UITextFieldDelegate>
@end

@implementation DictationHelper
{
    UITextField *secretTextField;
    id dictationController;
    DictationBlock completion;
    BOOL handled;
}

- (void) preheat
{
    if (!secretTextField)
    {
        secretTextField = [[UITextField alloc] initWithFrame:CGRectZero];
        UIWindow *window = [[UIApplication sharedApplication] keyWindow];
        [window addSubview:secretTextField];
        secretTextField.inputView = [[UIView alloc] init];
        secretTextField.delegate = self;
    }

    if (!dictationController)
    {
        MAKELIVE(UIDictationController);
        dictationController = [UIDictationController sharedInstance];
        [dictationController preheatIfNecessary];
    }
}

+ (instancetype) sharedInstance
{
    if (!sharedInstance)
    {
        sharedInstance = [[self alloc] init];
        [sharedInstance preheat];
    }
    return sharedInstance;
}


- (BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    NSString *tftext = textField.text;
    tftext = [tftext stringByReplacingCharactersInRange:range withString:string];
    [[NSNotificationCenter defaultCenter] postNotificationName:DictationStringResults object:tftext];

    if (completion) completion(tftext);

    // Treat this dictation as handled
    handled = YES;
    _inUse = NO;
    completion = nil;

    // Resign first responder
    [textField resignFirstResponder];

    return YES;
}

- (void) fallback
{
    // 1. Test completion
    if (!completion) return;

    // 2. Check for handled
    if (handled)
    {
        _inUse = NO;
        handled = NO;
        return;
    }

    // 3. Assume the dictation didn't work
    completion(nil);

    // 4. Reset everything
    handled = NO;
    _inUse = NO;
    completion = nil;

    // 5. Resign first responder
    [secretTextField resignFirstResponder];
}

-(void) startDictation:(CGFloat) whatever completion:(DictationBlock) completionBlock{
    if (completionBlock) completion = completionBlock;

    if (_inUse)
    {
        NSLog(@"Error: Dictation Helper already in use");
        return;
    }

    _inUse = YES;
    handled = NO;

    secretTextField.text = @"";
    [secretTextField becomeFirstResponder];

    [[UIDevice currentDevice] playInputClick];
    [dictationController startDictation];
}

- (void) dictateWithDuration: (CGFloat) numberOfSeconds
{
    if (_inUse)
    {
        NSLog(@"Error: Dictation Helper already in use");
        return;
    }

    _inUse = YES;
    handled = NO;

    secretTextField.text = @"";
    [secretTextField becomeFirstResponder];

    [[UIDevice currentDevice] playInputClick];
    [dictationController startDictation];
    [self performSelector:@selector(stopDictation) withObject:nil afterDelay:numberOfSeconds];
    [self performSelector:@selector(fallback) withObject:nil afterDelay:numberOfSeconds + 1.0f];
}

- (void) dictateWithDuration: (CGFloat) duration completion:(DictationBlock) completionBlock
{
    if (completionBlock) completion = completionBlock;
    [self dictateWithDuration:duration];
}

- (void) stopDictation
{
    [dictationController stopDictation];
}

- (void) stopDictationWithFallback
{
    [self performSelector:@selector(stopDictation) withObject:nil afterDelay:0.0];
    [self performSelector:@selector(fallback) withObject:nil afterDelay:1.0f];
}

@end

#undef MAKELIVE