1

iPhone で sqlite ストアを使用してコア データを使用する....コミックの issue# を含む文字列を持つコミック ブックのイメージ エンティティがたくさんあります。たとえば、次のようになります。image.imageTitle = @"Issue 12: Special Edition";

UI の一部では、ユーザーは問題番号を入力して次の問題にジャンプできます。このための私の最初のコードは sloooooooow でした。これは、imageAtIndex:Core Data に対して一度に 1 つのオブジェクトを照会するためです。数百の問題を超えると、最初のループを通過するだけで 40 秒以上かかる場合があります。

スローコード:

 // Seek forward from the next page to the right
 for (i = currentPage + 1; i < [self numberOfPages]; i++) {
  iterationString = [[self imageAtIndex:i] imageTitle];
  iterationNumber = [[iterationString stringByTrimmingCharactersInSet:nonDigits] intValue];

  if (issueNumber == iterationNumber) {
   keepLooking = NO;
   break;
  }
 }
 // If nothing was found to the right, seek forward from 0 to the current page
 if (i == [self numberOfPages] && keepLooking) {
  for (i = 0 ; i < currentPage; i++) {
   iterationString = [[self imageAtIndex:i] imageTitle];
   iterationNumber = [[iterationString stringByTrimmingCharactersInSet:nonDigits] intValue];

   if (issueNumber == iterationNumber) {
    keepLooking = NO;
    break;
   }
  }
 }

より効率的なソリューションを期待して、次のように Core Data に対して直接クエリを実行することにしました。

    NSString *issueNumber = @"12";
    NSString *issueWithWordBoundaries = [NSString stringWithFormat:@"\\b%@\\b",issueNumber];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(groupID == %@) AND (imageTitle CONTAINS %@)", groupID, issueWithWordBoundaries];

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
 NSEntityDescription *entity = [NSEntityDescription entityForName:@"CBImage" inManagedObjectContext:self.managedObjectContext];
 [fetchRequest setEntity:entity];

 [fetchRequest setPredicate:predicate];
 [fetchRequest setIncludesSubentities:NO]; // Not sure if this is needed, but just in case....

 // Execute the fetch
 NSError *error = nil;
 NSArray *fetchedObjects = [managedObjectContext executeFetchRequest:fetchRequest error:&error];

    // [fetchedImages count] == 0

Predicate Programming GuideICU regex specsの間で、\b が 12 の検索で 120、121、122 などを返すのを防ぐのに役立つと考えました。代わりに、ストアからは何も返されません!

一方、単語の境界を省略して代わりに を検索するとstringWithFormat:@"%@",issueNumber、12 から 129 から 412 まで、多数の管理対象オブジェクトが返されます。

この時点で、Core Data のConstraints and Limitationsの 1 つに遭遇したと推測できます。そうでない場合、私は何を間違っていますか? もしそうなら、完全一致単一フェッチの速度の両方を提供する回避策はありますか?

4

2 に答える 2

3

\bバックスペース文字を指します。試す

[NSString stringWithFormat:@"\\b%@\\b",issueNumber];
//                           ^^   ^^

また、正規表現一致を実行するには、CONTAINS ではなく MATCHES を使用します。

于 2010-05-19T08:25:13.947 に答える
1

単語の境界はニシンであることが判明しました: 私の問題は、この問題の変形でした: imageTitles で気にしなかったビットに一致するワイルドカードがなければ、正規表現は成功しませんでした。

したがって、NSPredicate を使用して正確なフレーズを見つける一般的な解決策は次のとおりです。

NSString *exactPhrase = @"phrase_you_hope_to_find_in_another_string";
NSString *regularExpression = [NSString stringWithFormat:@".*\\b%@\\b.*",exactPhrase];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"stringToSearch CONTAINS %@", exactPhrase];
// Assuming a string or an entity's string attribute named stringToSearch
于 2010-05-21T21:33:44.723 に答える