1

iOS アプリで検索したい事前設定された Coredata ファイルがあります。ファイルには、次のような単語が索引付けされています ~ (70,000 行) ~10 MB のファイル。

ad
adam
arm
apple
..
..
zen
zener

ファイルから Coredata を作成し、SQLLite にクエリを実行しました。たとえば、「a」で始まるすべての単語を教えてください。シミュレーターだと検索に300msecくらいかかるのにiPadだと2秒以上かかる?どうすればこれをより速くすることができますか? 他の検索エンジン タイプのアプリはデバイス上でどのように機能しますか?

//////////////////////////////////////////////////////////////////////
//This will get list of words begining with letters from search word
//////////////////////////////////////////////////////////////////////
-(void) FetchWords
{
NSString *entityName=@"KeyWord";
NSString *sortKey = @"word";
NSArray *fetchColumns = [[NSArray alloc] initWithObjects:@"word", nil];

//init fetch request
NSFetchRequest *req = [[NSFetchRequest alloc] init];

NSString *query = self.searchBar.text;

//
//split search phrase into words - searches words with any order and not case senitive - remove last space if any
//
NSMutableArray *words = [[query componentsSeparatedByString:@" "] mutableCopy];
if([words[words.count-1] isEqualToString:@""])
    [words removeObjectAtIndex:[words count]-1];

if(query.length)
{

    NSMutableArray *subpredicates = [NSMutableArray array];

    if(words.count >1)
    {
       [self GetMatchingCategoryCodes];
      //  NSLog(@"%@",categories);


        for (NSString *code in categories)
        {
            //intersection between last word and previous categories already filtered for previous words in search

           NSPredicate *pred = [NSPredicate predicateWithFormat:@"word BEGINSWITH[cd] %@ AND code BEGINSWITH [cd] %@",words[words.count-1],code]; 
           [subpredicates addObject:pred];
        }

      req.predicate = [NSCompoundPredicate orPredicateWithSubpredicates:subpredicates];

    }
    else
    {
       for(NSString *token in words)
       {
           NSPredicate *pred = [NSPredicate predicateWithFormat:@"word BEGINSWITH[cd] %@",token];
          [subpredicates addObject:pred]; 
       }
       req.predicate = [NSCompoundPredicate orPredicateWithSubpredicates:subpredicates];

    }
}


//setup request
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:context];
[req setEntity:entity];
[req setFetchBatchSize:100];

//sort descriptors
NSSortDescriptor *desc = [[NSSortDescriptor alloc] initWithKey:sortKey ascending:YES];
NSArray *descriptors = [NSArray arrayWithObject:desc];
[req setSortDescriptors:descriptors];

//for unique values - ignore repeatition
req.propertiesToFetch = fetchColumns;
req.returnsDistinctResults = YES;
req.resultType = NSDictionaryResultType;


//execute request
NSError *error;
Codes = [context executeFetchRequest:req error:&error];

//  NSLog(@"Fetched=%d",Codes.count);

}
4

3 に答える 3

0

これらの単語をテーブルビューで表示する場合は、NSFetchedResultsControllerの使用を検討し、キャッシュを有効にする必要があります。

于 2012-12-03T20:24:16.507 に答える
0

複数の最適化方法があります。

たとえば CONTAINS を使用すると、検索が遅くなります。Apple は、searchWords (またはその他のもの) と呼ばれる検索語に別のエンティティを使用することをお勧めします。そのストアでは、検索対象のすべての単語が小文字になり、アクセントが削除されます。これらの個別のエンティティには、それらを元のオブジェクトにリンクする関係があります。単語フィールドがインデックス化されていることを確認してください。

さらに、検索フィールドに入力された最初の文字だけがディスクにヒットする必要があります。最初の文字の後は、既にメモリにあるものの検索結果のみを絞り込む必要があります。

既に持っている述語を使用して (最初の文字検索から) メモリ内にあるその配列をフィルター処理し、不要なフェッチ要求を実行しないようにする必要があります。

さらに、既にメモリ内にあるデータ (NSFetchedResultsController 内に存在するなど) を検索する場合は、検索全体でメモリ内のオブジェクトのみにヒットする必要があります。ディスクに出かけるのは不要で、ひどく無駄です。ResultsController を使用しない場合は、最初のヒット後にメモリ内で検索のみを実行する配列にデータをキャッシュすることができます。これにより、リクエストも高速化されます。

したがって、バッチサイズとキャッシュを有効にして FetchedResultsController を使用すると、検索も改善されるはずです。

ところで:キーボードの遅れを避けるために、バックグラウンドスレッドでこれらの「激しい」検索を実行できます。ただし、一度に 1 つのバックグラウンド リクエストのみを実行し、最新の結果のみをフェッチするようにする必要があります。スレッドの優先度を低くすると、UI のパフォーマンスが向上します。

サンプルコードを使用してコアデータ検索の速度を向上させることに関する wwdc があります:
Apple WWDC Core Data
Optimizing Core Data Performance on iPhone OS (スライド)
Optimizing Core Data Performance on iPhone OS (ビデオ)

于 2012-12-03T20:34:25.150 に答える
0

レイジー ロードを試して、出力を 50 以下のアイテムに制限することもできます。ユーザーが結果リストをスクロールすると、必要に応じてさらに取得します。

于 2012-12-03T20:19:21.777 に答える