作者leondemon (狗狗)
看板MacDev
标题[问题] 在Obj-C 下做搜寻字串的功能
时间Sat Sep 22 21:22:15 2012
这阵子开发一个英汉字典的功能时 发现一些问题
主要是利用 UISearchDisplayController 来呈现搜寻字典的UI
在search时 并不是利用predicate来重新fetch
而是在fetchedObjects中找出最接近符合字串的index
并利用table view的-scrollToRowAtIndexPath:atScrollPosition:animated:
跳到搜寻到最接近的cell
这样User还是能在全部的字典内上下卷动浏览字库
搜寻流程总共含下面几个步骤:
1. 在UISearchBarDelegate的方法来触发搜寻字典功能
- (void)searchBar:(UISearchBar *)searchBar
textDidChange:(NSString *)searchText{
// 在有输入字串的情况下进行非同步搜寻
if (![searchText isEqualToString:@""]) {
[self asyncSearchText:searchText];
}
}
2. 进行非同步搜寻字串
- (void)asyncSearchText:(NSString*)text{
[self.operationQueue addOperationWithBlock:^{
[self searchText:text];
}
}
- (void)searchText:(NSString*)text{
// 利用NSArray的-indexOfObjectPassingTest:
// 来对之前fetch出来的vocabularies进行字串比对搜寻
// 这边是简化的code,事实上我将字典依单字的字母开头分成A-Z 26个资料库
// 在search时,会依照字首来决定使用哪个fetchedObjects做进一步搜寻
// **fetchedObjects已经经过NSSortDescriptor的caseInsensitiveCompare:排序
NSArray *vocabularies = self.fetchedResultsController.fetchedObjects;
// Problem 1: 请见後面讨论
NSInteger foundRow = [vocabularies indexOfObjectPassingTest:
^BOOL(id obj, NSUInteger idx, BOOL *stop) {
// 将fetchedObjects中每个Vocabulary物件进行比对
Vocabulary *vocabulary = obj;
NSComparisonResult comparisonResult = [vocabulary.word
compare:text options:NSCaseInsensitiveSearch];
if (comparisonResult != NSOrderedAscending) {
*stop = YES;
return YES;
}
return NO;
}
// 获得indexPath
NSIndexPath *foundIndexPath = [self foundIndexPathForFoundRow:foundRow
forText:text];
// 通知更新searchResultsTableView
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self searchedText:text foundAtIndexPath:foundIndexPath];
}];
}
3. 更新searchResultsTableView
- (void)searchedText:(NSString*)text foundAtIndexPath:(NSIndexPath*)indexPath{
// Problem 2: 请见後面讨论
[self.searchDisplayController.searchResultsTableView
scrollToRowAtIndexPath:indexPath
atScrollPosition:UITableViewScrollPositionTop
animated:YES];
}
以上是简化的一个流程 以上程式码在搜寻时是可以work
但是当键盘输入过於快速时(大约超过每秒2个字母) 会发生以下问题:
Problem 1:
当输入过於快速时 发现到async的operation会一直卡在isExecuting的状态
发现是卡在NSArray的-indexOfObjectPassingTest:里面出不来 不知道为什麽
朋友说试着改用suffix tree来做搜寻 (不过我还没研究...)
目前字串搜寻速度效率我可以接受 只不过不知道为什麽会发生这种情况... Orz
Problem 2:
当输入过於快速时 会发生UI整个卡住不能动的情况
把-scrollToRowAtIndexPath:atScrollPosition:animate:给comment out就不会卡住
原本推测是前一个scroll的animation还没结束就实行下一个scroll造成
但是利用mainQueue 进行 serial operation 也是一样会卡(就是卷完一个再卷下一个)
我看其他字典软体的App都可以做出来我想要的结果 可是我遇到这些问题不知道该怎麽办
希望大家可以给一点意见..
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 111.80.236.201
1F:推 tentenlee:动画关掉勒?? 09/23 00:59
2F:→ leondemon:动画关掉UI就不会卡 但是搜寻task卡住的问题还在 09/23 22:40