Работа с частными структурами распознавания речи на iOS 8
Мне нужно добавить распознавание речи в приложение для личного проекта.
Мне нужна встроенная в iOS структура распознавания речи, потому что она быстрая, точная и может также распознавать ваши имена контактов и другую информацию о себе.
До сих пор, я думаю, что я нашел фреймворк, который содержит заголовки для распознавания речи на iOS 8: SAObjects.framework Я получил заголовки Github и успешно добавил их в свой проект Xcode. Заголовки, которые я пробовал до сих пор:
<SAObjects/SASRecognition.h>
<SAObjects/SASStartSpeechDictation.h>
<SAObjects/SASSpeechRecognized.h>
Однако я не уверен, как с ними работать. Например, это два возможных метода, которые могут запустить распознавание речи:
SASStartSpeechDictation *object1 = [SASStartSpeechDictation startSpeechDictation];
SASSpeechRecognized *object2 = [SASSpeechRecognized speechRecognized];
Когда я отлаживаю его, я не могу найти ни одной строки ни в одном из этих объектов. Так что, очевидно, что-то не так. Может быть, мне нужно установить уведомление наблюдателя?
Другое решение может состоять в том, чтобы начать диктовку (через клавиатуру) в скрытое текстовое поле (без отображения клавиатуры). Например, действие "Активатор" для устройств с джейлбрейком, если вы с ним знакомы. Но я не нашел никаких методов, которые могли бы запустить диктовку клавиатуры или исходный код действия Activator, чтобы выяснить это.
Может быть, кто-то экспериментировал с этими вещами и может мне помочь?
Скажите, пожалуйста, если вам нужна дополнительная информация по этому вопросу:)
Большое спасибо!
1 ответ
Итак, мне удалось найти ответ самому. К счастью, я нашел репозиторий Github с некоторым полезным кодом: https://github.com/erica/useful-things
Код, который я нашел, находится в каталоге appstore unsafe pack/DictationHelper. Этот код помогает использовать UIDictationController и запускать и останавливать Dictation, а также получать текстовое значение. Конечно, без каких-либо текстовых полей...
Важно: чтобы это работало, вам нужно иметь заголовки инфраструктуры UIKit, связать инфраструктуру с Target и импортировать их в Project!
Тем не менее, я немного изменил код, потому что пример кода доступен только в течение определенного времени. Мне нужно было перестать говорить, нажав кнопку. Это модифицированный код для тех, кто может быть заинтересован в будущем:
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