美文网首页iOS技术篇@IT·互联网程序员
iOS搜索 && 讯飞语音的使用

iOS搜索 && 讯飞语音的使用

作者: Kevin_wzx | 来源:发表于2016-08-29 11:44 被阅读373次

    搜索

    1.简单认识

    由于表格视图可以呈现大量的信息,因此对这些信息进行搜索是很常见的,可以为表格视图添加搜索条(UISearchBar),根据搜索结果来刷新表格视图。
    这里讲解三种搜索:
    (1)普通的UITableView搜索 ,
    (2)和在此基础上的语音搜索,
    (3)以及UISearchDisplayController(苹果自带封装好的)

    2.UITableView搜索

    UIKit里有一个叫做UISearchBar的组件,能让用户迅速的筛选有用的信息。其实UISearchBar挺懒的。它本身不做任何搜索。UISearchBar会提供一个基本的iOS搜索栏界面。它就像一个中等干部一样,最在行的就是让别人做事情。(像我以前的老板一样!)UISearchBar类用delegate协议的方式来告诉app的其他部分用户正在搜索栏中做什么。你需要自己编写对比字符串和过滤搜索的函数。自定义的搜索功能让你对搜索过滤有更多的控制,你能够根据自己app的特点来修改搜索结果,让你的用户体验更迅速和智能的搜索。

    @interface ViewController () <UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate> {
    
     UITableView *myTableView;
     UISearchBar *mySearchBar; 
     NSArray *currentArray; // 指向当前正在使用的数据模型数组的指针
     NSMutableArray *dataArray; // 保存固定数据的数组 
     NSMutableArray *resultsArray; // 装搜索结果的数组
    }
    @end
    
    - (void) customizeSearchBar {
    
     mySearchBar = [[UISearchBar alloc]initWithFrame:CGRectMake(0, 0, 0, 40)]; 
     mySearchBar.placeholder = @"请输入要查找的名字"; 
     mySearchBar.showsCancelButton = YES; 
     mySearchBar.showsBookmarkButton = YES; 
     [mySearchBar setImage:[UIImage imageNamed:@"Dudu.jpg"] forSearchBarIcon:UISearchBarIconBookmark state:UIControlStateNormal]; 
     mySearchBar.delegate = self;
     [myTableView setTableHeaderView:mySearchBar];
    
    }
    
    #pragma mark UISearchBarDelegate回调方法
    // 点击键盘上的搜索按钮
    - (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar { 
    if (!resultsArray) { 
        resultsArray = [NSMutableArray array]; 
    } else { 
       [resultsArray removeAllObjects]; 
    }
     NSString *str = searchBar.text; 
    for (CDPerson *tempPerson in dataArray) {
         NSRange range = [tempPerson.name rangeOfString:str]; 
        if (range.location != NSNotFound) { 
           [resultsArray addObject:tempPerson];
        } 
    } 
        // 将搜索结果作为表格视图的模型 
        currentArray = resultsArray; 
        [myTableView reloadData];
    }
    
    // 点击搜索栏上的取消按钮的回调方法
    - (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar { 
         // 使用原来的数据模型
         currentArray = dataArray; 
        [myTableView reloadData];
    }
    
    3.语音搜索

    在移动应用中使用语音识别功能后,原来需要键盘输入的地方可以直接使用语音进行输入,从而解放用户的双手提供更好的用户体验。目前,讯飞MSC在中文语音识别中用得较多,下面就以讯飞语音识别为例讲解如何实现语音搜索功能。

    可以在讯飞开放平台的SDK下载中心下载讯飞提供的语音听写功能,当然需要注册账号并获得使用SDK的APPID,下载后的文件夹中包含了文档、库文件和样例程序,可以直接阅读文档或参考样例程序来实现自己的语音搜索功能。

    创建项目后,需要向项目中加入讯飞的库文件以及它依赖的其他库文件,可以在下图所示的位置进行添加,需要添加的库文件也如下图所示,其他的库文件可以通过Xcode的自动链接器自动加入。

    这里写图片描述

    可以对讯飞提供的SDK进行二次封装,使其变成更容易使用的API(只用一行代码就可以使用它的功能),代码如下所示。

    屏幕快照 2016-08-30 下午2.36.55.png 屏幕快照 2016-08-30 下午2.38.13.png 屏幕快照 2016-08-30 下午2.42.51.png 屏幕快照 2016-08-30 下午2.39.53.png

    上面的代码在讯飞提供的样例程序中可以找到,无需自行编写,但是可以对其中的一些参数进行设置,例如language(语种)、vadEos(语音结束后的超时点)、vadBos(语音开始前的超时点)、speechTimeout(语音长度达到多少时间超时)等。

    #import <Foundation/Foundation.h>
    #import "iflyMSC/IFlyMSC.h"
    
    typedef void(^CDVoiceHandler)(NSString *);
    
    @interface CDVoice : NSObject <IFlyRecognizerViewDelegate> { 
    IFlyRecognizerView *rView;
    }
    
    @property (nonatomic, copy) CDVoiceHandler voiceHandler;
    
    + (instancetype) sharedInstance;
    
    - (void) voiceToTextString:(CDVoiceHandler) handler;
    
    @end
    

    .m文件

    #import "CDVoice.h"
    #import "IATConfig.h"
    
    #define LEFT_FOR_RV 50#define TOP_FOR_RV 50
    @implementation CDVoice
    
    - (instancetype) init { 
        @throw [NSException exceptionWithName:@"CDVoiceException" reason:@"不允许使用初始化方法" userInfo:nil];
    }
    
    - (instancetype) initPrivate { 
       if (self = [super init]) { 
          // Do some initialization here!!!
       } return self;
    }
    
    + (instancetype) sharedInstance { 
        static CDVoice *instance = nil;
        if (!instance) {
           instance = [[self alloc] initPrivate]; 
        } return instance;
    }
    
    - (void) voiceToTextString:(CDVoiceHandler) handler{
    
        if (!rView) {
    
            rView = [[IFlyRecognizerView alloc] initWithOrigin:CGPointMake(LEFT_FOR_RV, TOP_FOR_RV)]; 
            [rView setParameter:@"" forKey:[IFlySpeechConstant PARAMS]]; 
    
            //设置听写模式 
            [rView setParameter:@"iat" forKey:[IFlySpeechConstant IFLY_DOMAIN]]; 
            rView.delegate = self;
            IATConfig *instance = [IATConfig sharedInstance]; 
    
            //设置最长录音时间 
            [rView setParameter:instance.speechTimeout forKey:[IFlySpeechConstant SPEECH_TIMEOUT]]; 
    
            //设置后端点 
            [rView setParameter:instance.vadEos forKey:  [IFlySpeechConstant VAD_EOS]]; 
    
            //设置前端点 
            [rView setParameter:instance.vadBos forKey:[IFlySpeechConstant VAD_BOS]];  
    
            //设置采样率,推荐使用16K 
            [rView setParameter:instance.sampleRate forKey:[IFlySpeechConstant SAMPLE_RATE]]; 
            if ([instance.language isEqualToString:[IATConfig chinese]]) { 
    
                //设置语言 
                [rView setParameter:instance.language forKey:[IFlySpeechConstant LANGUAGE]]; 
                //设置方言
                [rView setParameter:instance.accent forKey:[IFlySpeechConstant ACCENT]];
             } else if ([instance.language isEqualToString:[IATConfig english]]) { 
    
                //设置语言 
                [rView setParameter:instance.language forKey:[IFlySpeechConstant LANGUAGE]]; 
             } 
             //设置是否返回标点符号 
            [rView setParameter:instance.dot forKey:[IFlySpeechConstant ASR_PTT]];
         } 
         // 绑定语音识别完成后做回调的Block  
         self.voiceHandler = handler; 
    
         [rView start];
    }
    
    // 语音识别完成的回调
    - (void)onResult:(NSArray *)resultArray isLast:(BOOL) isLast {
    
        NSMutableString *result = [[NSMutableString alloc] init]; 
        NSMutableString * resultString = [[NSMutableString alloc]init]; 
        NSDictionary *dic = resultArray[0]; 
    
        for (NSString *key in dic) { 
             [result appendFormat:@"%@",key]; 
             NSString * resultFromJson = [self stringFromABNFJson:result];
             if (! [resultString isEqualToString:@" "]) {    
                 [resultString appendString:resultFromJson];       
             } 
        } 
        if (!isLast && self.voiceHandler) {  
              self.voiceHandler(resultString); 
        }
    }
    
    // 语音识别出错的回调方法
    - (void)onError: (IFlySpeechError *) error { 
         if (error.errorCode) {
             NSLog(@"%@", error); 
         }
    }
    
    // 从JSON格式的数据中提取语音数据(该方法可以在官方Demo的代码中找到)
    - (NSString *)stringFromABNFJson: (NSString *) params {
     
        if (!params) { 
            return nil; 
        } 
        NSMutableString *tempStr = [[NSMutableString alloc] init]; 
        NSDictionary *resultDic = [NSJSONSerialization JSONObjectWithData:[params dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil];
        NSArray *wordArray = [resultDic objectForKey:@"ws"];
    
        for (int i = 0; i < [wordArray count]; i++) {  
       
             NSDictionary *wsDic = [wordArray objectAtIndex: i]; 
             NSArray *cwArray = [wsDic objectForKey:@"cw"]; 
             for (int j = 0; j < [cwArray count]; j++) { 
     
                  NSDictionary *wDic = [cwArray objectAtIndex:j]; 
                  NSString *str = [wDic objectForKey:@"w"]; [tempStr appendString: str]; 
             }
         } 
          return tempStr;
    }
    @end
    

    到此为止,我们已经封装好了自己的API,要使用它非常简单,代码如下所示。

    #import "AppDelegate.h"
    #import "iflyMSC/IFlyMSC.h"
    @interface AppDelegate ()
    
    @end
    @implementation AppDelegate
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
    
       // 将自己申请的APPID通过IFlySpeechUtility工具类进行注册 
       [IFlySpeechUtility createUtility:@"appid=自己申请的APPID"];    
       return YES;
    }
    @end
    

    下面完成了一个非常简单的应用来使用我们封装好的语音识别功能。

    屏幕快照 2016-08-30 下午3.20.38.png

    运行效果如下图所示,点击OK按钮开始进行语音识别,完成后将识别的内容输入文本框中


    这里写图片描述
    这里写图片描述

     我们可以对搜索栏中的书签按钮进行定制,在点击通过调用我们封装好的代码后产生语音识别的视图,然后将识别的结果填入搜索栏中。

    - (void) customizeSearchBar { 
        mySearchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 0, 40)]; 
        mySearchBar.placeholder = @"请输入要查找的名字"; 
        mySearchBar.showsCancelButton = YES; 
        mySearchBar.showsBookmarkButton = YES; 
        [mySearchBar setImage:[UIImage imageNamed:@"Dudu.jpg"] forSearchBarIcon:UISearchBarIconBookmark state:UIControlStateNormal]; 
        mySearchBar.delegate = self; 
        [myTableView setTableHeaderView:mySearchBar];
    }
    
    // 点击书签按钮的回调方法
    - (void)searchBarBookmarkButtonClicked:(UISearchBar *)searchBar {
     
         [[CDVoice sharedInstance] voiceToTextString:^(NSString *str) { 
    
            mySearchBar.text = str;
            [mySearchBar becomeFirstResponder];
         }];
    }
    
    4.UISearchDisplayController

    UISearchDisplayController 是苹果专为 UITableView 搜索封装的一个类。里面内置了一个 UITableView 用于显示搜索的结果。它可以和一个需要搜索功能的controller 关联起来,其它的像原 TableView 和搜索结果TableView 的切换, mask 的显示等等都封装好了,使用起来非常非常的简单。特别是要实现全屏搜索时使用最多。全屏搜索的意思是如果你用了 NavigationBar 当点击搜索框时 TableView 会自动弹上去覆盖NavigationBar,达到一种全屏搜索的效果,这一切 UISearchDisplayController 都封装好了,如果自己写就比较麻烦一些。

    效果图:



    关键代码

    屏幕快照 2016-08-30 下午3.47.30.png 屏幕快照 2016-08-30 下午3.47.42.png

    相关文章

      网友评论

        本文标题:iOS搜索 && 讯飞语音的使用

        本文链接:https://www.haomeiwen.com/subject/scmxettx.html