1

I'm building a customised UITableViewController that shows all the contacts in the iPhone and behaves like the ABPeoplePickerNavigationController. Meaning it also supports searching the contacts. I'm doing this with the code here.

I've implemented the search ability using Search Bar and Search Display Controller, and I followed this tutorial by appcoda.

Since my NSArray is an array of ABRecordRef my method of filterContentForSearchText: scope: is this:

- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
    NSPredicate *resultPredicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
        ABRecordRef person = (__bridge ABRecordRef)evaluatedObject;
        NSString * fullname = [self getFullnameOfRecord:person];

        NSPredicate *tmpPredicate = [NSPredicate predicateWithFormat:@"self contains[c] %@", searchText];
        if ([tmpPredicate evaluateWithObject:fullname]) {
            return YES;
        } else {
            NSLog(@"tmpPredicate didn't match");
            return NO;
        }
    }];

    searchResults = [self.allContacts filteredArrayUsingPredicate:resultPredicate];
}

The search results are fine, but since this is a very large array, it works very slowly. Is there a way I could improve the performance of this search mechanism?

Update: As @Eiko suggested, I tried replacing the inner NSPredicate with this code:

NSRange range = [fullname rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (range.length > 0) {
    return YES;
} else {
    return NO;
}

But it didn't improve the performance.

4

2 回答 2

1

您应该尝试使用分析器来找到最薄弱的线,但我认为问题在于每次都会为每个条目评估谓词块。

我建议您为 ABRecordRef 创建自己的包装类(比方说 RecordWrapper),它将包含指向 ABRecordRef 的链接以及整个数据并缓存一些常用和重要的值(例如 fullName),您可以在加载联系人列表时获取它一次.

然后,如果您有一个 RecordWrapper* 对象数组,您可以通过调用来过滤

NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:@"fullName contains[c] %@", searchText];
searchResults = [self.allContactsWrappers filteredArrayUsingPredicate:resultPredicate];

这应该会显着提高过滤速度。

于 2014-08-18T15:08:42.697 回答
0

“非常大的阵列”?我猜联系人列表相当小,通常 < 1k 个元素。

话虽这么说,谓词的东西可能很贵,关于这个答案,简单的列举可能是最快的。不过,我建议在真实设备上测试(和配置文件)。

我想创建谓词可能是一项代价高昂的操作(它们需要编译吗?),因此您可以重用它,或者更好的是,只需对fullname自己进行一些“包含检查”(只需使用 进行搜索rangeOfString:options:),省略谓词。

于 2014-08-18T13:43:05.733 回答