iOS searchBar当搜索页输入拼音且用户尚未选择时动态搜索

需求:搜索页,输入拼音,尚未选择时最好也开始动态搜索(在此状态下单击列表会产生错误)。可参考百度地图机制

当你输入关键词搜索的时候,会弹出一个提示框。要实现这个效果,你可能会考虑使用UISearchBar的
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
这个delegate方法进行搜索提示词汇的获取。

但若中文输入法输入拼音字母没有选词的时候,是不会触发这个方法的,也就实现不了Safari浏览器地址栏的效果。

给当前控制器添加一个属性:

/// 监听并保存用户输入的拼音
@property (nonatomic, strong) NSMutableString *currentSearchText;

设置searchBar的代理,实现以下代理方法

#pragma mark -- UISearchBarDelegate
- (BOOL)searchBar:(UISearchBar *)searchBar shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    
    // 获得需要进行搜索的关键字, 此种方式获取的词汇:比如拼音输入beijing时,获取的是bei jing
//      self.currentSearchText = [[searchBar.text stringByReplacingCharactersInRange:range withString:text] mutableCopy];
    
    // 项目中使用的这个,此种方式获取的是用户输入的拼音,比如beijing,就是beijing
    // range代表用户输入的字符长度, text是用户输入的字符
    if (!range.length) {
        // 给当前搜索的字符串拼接字符
        [self.currentSearchText appendFormat:@"%@", text];
    } else {
        // 表示用户删除了一个字符,删除当前搜索字符串最后一个字符
        [self.currentSearchText  deleteCharactersInRange:NSMakeRange(self.currentSearchText.length-1,1)]; //
        
    }

//  手动调用一次此方法开始搜索,因为项目中发送服务器请求的方法在这里面处理的
    [self searchBar:searchBar textDidChange:self.currentSearchText];
    
    [UISearchBar placeholderHidden:searchBar Text:text Editor:YES];
    
    return YES;
}

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
  // 此方法中再重新赋值给currentSearchText,与非拼音搜索时保持一致
    self.currentSearchText = [NSMutableString stringWithFormat:@"%@", searchText];
    DLog(@"当前搜索的关键词是:%@", self.currentSearchText);

// 下面为处理业务逻辑啦
}

3月23日遇到的问题:

问题:
当使用系统九宫格输入法拼音搜索,但未确认时, 代理方法回调的text为:➋➌➍➎➏➐➑➒,也就是说未选择时获取到的是这个字母所在九宫格的哪一个格子里面(从2开始,最后一个是9,第一个格子被,。?!暂用了),只有用户选择或确认了才会回调汉字或拼音,当然这种情况只有在九宫格拼音时才会有,九宫格英文i输入无问题,其实这是因为一个格子里面好几个字母,苹果也不知道用户真实输入的哪个,只能通过用户输入的字母,反馈给用户推荐的词汇让用户选择;

问题分析:
刚才已经想到苹果会反馈给用户词汇了,那么就可以从这开始下手,在Keyboard上方会一个view,view上面有两个横条,一个显示用户输入的关联拼音,一个是通过关联拼音推荐的汉字词汇;
通过Xcode视图工具可以看到很清晰的结构,keyboard上方两个view的类型都是UIKBCandidateCollectionView(私有),是UICollectionView的子类,他们的父控件共同为UIKeyboardCandidateBar,而且代理方法和数据源也都是UIKeyboardCandidateBar,那每个关联词汇也就是一个cell,既然数据源和代理都是UIKeyboardCandidateBar,那么我们只要拿到从这个类拿到数据源,就可以得到用户输入的关联拼音和关联词汇啦;

Snip20170324_4.png
Snip20170324_6.png

解决方法:
既然找到了数据源所在的类,UIKeyboardCandidateBar继承UIView,且通过Xcode视图工具发现这个类是唯一的, 那么我们可以递归遍历keyboard所在的view,找到这个数据源对象,并通过runtime获取这个对象的所有属性,再从这里找到数据源数组即可,果然我找到了三个集合,_candidateViews(存放那两个view的数组),_filteredCandidates(用户输入的拼音过滤的关联词汇), _candidateResultSet(存放用户输入的关联拼音,还有_initiallyHiddenCandidates数组存的其实就是_filteredCandidates) ,数据源的内容就是那两个view展示的内容,我们可以直接通过KVC获取到这些属性;
另外这个对象的另外一个属性_inlineText的值就是我们输入键盘时,搜索框真实显示的拼音,郁闷再次测试尽然是上一次输入的;

Snip20170324_3.png
Snip20170324_1.png

推荐阅读更多精彩内容