2012-01-11 7 views
1

コアデータに多数のjsonフィードを格納する必要があります。アプリが読み込まれるまでに時間がかかりすぎるので、一度に呼び出すことはできないほど多くのフィードがあります。アプリ起動時に最も重要なものを呼び出し、残りの部分をアプリ全体に分割します。しかし、私はまた、これらをコアデータに格納する必要があります。NSPredicateを使用して、データを挿入するときにエンティティに値が既に含まれているかどうかを確認します。

最初のビューは、テーブルビューであり、その中に名前があります。名前をクリックすると、次のビューに送られます。そこにはテキストと写真がいくつかあります。したがって、2番目のビューがロードされると、Webサービスにリクエストを送信し、サービスの回答をコアデータに保存します。

同じtableviewcellを2回クリックすると、呼び出されたサービスの情報がCore Dataに2回書き込まれ、重複値が作成されます。私はこれを避けたい。

私のしたいことは、自分のエンティティにすでに一意の値が含まれているかどうかを確認することです。存在する場合は、コアデータに保存しないでください。そうでない場合は、保管してください。ここで

は私の方法です:

-(void)addImage:(NSManagedObjectContext *)context withImageUrl:(NSString *)imageUrl{ 
NSFetchedResultsController *fetchedResultsController = [self fetchObjectsFromEntity:@"Image" withContext:context andSortKey:@"imageUrl"]; 

[fetchedResultsController.fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"imageUrl contains[cd] %@" , imageUrl]]; 


if (//WHAT TO PUT HERE?) { 
    NSLog(@"Doesn't exist"); 
    Image *image = [NSEntityDescription insertNewObjectForEntityForName:@"Image" inManagedObjectContext:context]; 
    image.imageUrl = imageUrl; 
}else{ 
    NSLog(@"Already exists"); 
} 


-(NSFetchedResultsController *)fetchObjectsFromEntity:(NSString *)entityName withContext:(NSManagedObjectContext *)context andSortKey:(NSString *)key{ 
NSError *error; 
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]init]; 
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:context]; 
[fetchRequest setEntity:entity]; 

if (key != nil) { 

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]initWithKey:key ascending:YES]; 
    NSArray *sortDescs = [[NSArray alloc]initWithObjects:sortDescriptor, nil]; 
    [fetchRequest setSortDescriptors:sortDescs]; 
} 

NSFetchedResultsController *fetchedResultController = [[NSFetchedResultsController alloc]initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:nil cacheName:@"Root"]; 

if (![fetchedResultController performFetch:&error]) { 
    NSLog(@"Error: %@" , error); 
}   

    return fetchedResultController; 
} 

誰もが、私はこれを達成する方法のアイデアを持っていますか?述語が間違っていますか?述語が真であるかどうかを確認するにはどうすればよいですか?

助けていただけたら幸いです!

答えて

2

あなたがやっていることは非常に高価になるでしょう。 NSFetchRequestを実行するたびにSQL(高価)を実行し、I/O(高価)を実行することを覚えておく必要があります。あなたの目標は、あなたがそれを行う回数に制限することです。

ユニークなキー(あなたのケースではimageURL)のリストを取得してからフェッチリクエストを実行して、そのイメージURLのどれが既に店舗にあるのかを確認することができれば、この場合、約10倍)。

また

、あなたが実際のオブジェクトでは興味がないことから、ちょうど彼らが存在するかどうか、あなたは自分のkeymすなわち[NSArray arrayWithObject:@"imageUrl"]含むフェッチ要求のresultTypeからpropertiesToFetchNSDictionaryResultTypeへと設定し、アレイを設定する必要があります。

最後に、文字列の比較は非常に高価です。 @"imageUrl contains[cd] %@"を使用しないでください。それは、データベースが多くの作業を行うことが必要でした。数字キーがある場合、たとえばあなたが数値比較を使用することができるので、物事をより速くする64ビットの数字。

このすべてをまとめると、固有のキー属性がuniqueIDとなっているとします。このようなフェッチ要求を実行することができます

- (NSArray *)keysMissingInStoreFromKeys:(NSArray *)someKeys; 
{ 
    NSFetchRequest *r = [NSFetchRequest fetchRequestWithEntityName:@"Image"]; 
    [r setResultType:NSDictionaryResultType]; 
    [r setPropertiesToFetch:[NSArray arrayWithObject:@"uniqueID"]; 
    NSPredicate *p = [NSPredicate predicateWithFormat:@"uniqueID IN %@", someKeys]; 
    [r setPredicate:p]; 
    NSError *error = nil; 
    NSArray *result = [moc executeFetchRequest:r error:&error]; 
    NSAssert(result != nil, @"Fetch failed: %@", error); 
    NSMutableArray *missingKeys = [someKeys mutableCopy]; 
    for (NSDictionary *values in result) { 
     id uniqueID = [values objectForKey:@"uniqueID"]; 
     [missingKeys removeObject:uniqueID]; 
    } 
    return missingKeys; 
} 

希望します。

関連する問題