1

iPhone のすべての連絡先を表示し、ABPeoplePickerNavigationController のように動作するカスタマイズされた UITableViewController を構築しています。つまり、連絡先の検索もサポートしています。私はここのコードでこれをやっています。

を使用して検索機能を実装し、appcoda によるSearch Bar and Search Display Controllerこのチュートリアルに従いました。

私の NSArray はABRecordRef私のメソッドの配列であるため、filterContentForSearchText: scope:これは次のとおりです。

- (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];
}

検索結果は問題ありませんが、これは非常に大きな配列であるため、動作が非常に遅くなります。この検索メカニズムのパフォーマンスを向上させる方法はありますか?

更新: @Eiko が示唆したように、内側の NSPredicate を次のコードに置き換えてみました。

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

しかし、それはパフォーマンスを改善しませんでした。

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 に答える