私が取り組んでいるアプリは、Web サービスの呼び出しを通じてデータベースとの同期を維持する必要があります。
最初に約 300k レコードを挿入する必要があり、これにはかなりの時間がかかります。最初のダウンロード後、更新 Web サービスを呼び出して、それ以降に変更されたすべてのレコードを取得します。
更新の呼び出し中に、そのオブジェクトが既に存在するかどうかを最初に確認する必要があるため、更新プロセスが大幅に遅くなります。通常、朝には約 5,000 件のレコードを更新する必要があり、単純に 300,000 件のレコードを挿入する場合とほぼ同じ時間がかかります。
コードは以下です。これを行うためのより高速で効率的な方法はありますか?
code in loop when iterating through JSON records from server
if(isUpdating)
{
CaseStatusCode *oldObj = [CaseStatusCode doesExist:[record valueForKey:@"JSONData"] uid:[record valueForKey:@"RecordUID"] inContext:temporaryContext];
if(oldObj) //it exists
{
[oldObj initWithJSONSting:[record valueForKey:@"JSONData"]];
}
else //create new
{
NSEntityDescription *desc = [NSEntityDescription entityForName:NSStringFromClass([CaseStatusCode class]) inManagedObjectContext:temporaryContext];
CaseStatusCode *worker = [[CaseStatusCode alloc] initWithEntity:desc insertIntoManagedObjectContext:temporaryContext];
[worker initWithJSONSting:[record valueForKey:@"JSONData"]];
}
}
doExist 関数
+ (CaseStatusCode *)doesExist:(NSString *)jsonString uid:(NSString *)uid inContext:(NSManagedObjectContext *)moc
{
SBJsonParser *parser = [[SBJsonParser alloc] init];
NSError *e;
NSDictionary *jsonObj = [parser objectWithString:jsonString error:&e];
if(uid || NULL_TO_NIL([jsonObj valueForKey:@"CaseStatusCodeUID"]))
{
if(jsonObj)
{
uid = [jsonObj valueForKey:@"CaseStatusCodeUID"];
}
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:[self entityName]];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"caseStatusCodeUID ==[cd] %@", uid]];
[fetchRequest setFetchLimit:1];
NSError *error = nil;
if ([moc countForFetchRequest:fetchRequest error:&error] == 0) {
NSLog(@"!!!WARN: NO Object Matches for pred: %@", fetchRequest.predicate);
return nil;
}
else
{
// fetch your object
CaseStatusCode *result = [[moc executeFetchRequest:fetchRequest error:&error] lastObject];
if (error != nil) {
NSLog(@"ERROR: %@ %@", [error localizedDescription], [error userInfo]);
return nil;
}
return result;
}
}
return nil;
}
初期化コード
- (void)initWithJSONSting:(NSString *)jsonString
{
SBJsonParser *parser = [[SBJsonParser alloc] init];
NSError *e;
NSDictionary *jsonObj = [parser objectWithString:jsonString error:&e];
if(e)
{
NSLog(@"JSON Error Creating State: %@", [e localizedDescription]);
}
else
{
MySingleton *globals = [MySingleton sharedInstance];
self.token = globals.token;
self.CaseStatusCodeUID = NULL_TO_NIL([jsonObj valueForKey:@"CaseStatusCodeUID"]);
self.CaseStatusCode = NULL_TO_NIL([jsonObj valueForKey:@"CaseStatusCode"]);
self.Active = NULL_TO_NIL([jsonObj valueForKey:@"Active"]);
self.desc = NULL_TO_NIL([jsonObj valueForKey:@"Description"]);
self.BaseStatus = NULL_TO_NIL([jsonObj valueForKey:@"BaseStatus"]);
}
}
ありがとう。
編集私はリンゴの例に従おうとしています。UID の NSArray を作成してから、IN 述語を使用してフェッチ要求を作成しています。返される結果は 0 で、その UID を持つそのタイプのオブジェクトがあることを確認しました。
uidArray = (NSMutableArray *)[uidArray sortedArrayUsingSelector:@selector(compare:)];
viewName = @"CaseStatusCode";
uidKey = @"caseStatusCodeUID";
// create the fetch request to get all CaseStatusCode matching the IDs
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:viewName inManagedObjectContext:temporaryContext]];
[fetchRequest setPredicate: [NSPredicate predicateWithFormat: @"%@ IN %@",uidKey, uidArray]];
// Make sure the results are sorted as well.
[fetchRequest setSortDescriptors:@[ [[NSSortDescriptor alloc] initWithKey:uidKey ascending:YES] ]];
// Execute the fetch.
NSError *error;
NSArray *matchingObjectsArray = [temporaryContext executeFetchRequest:fetchRequest error:&error];
NSLog(@"fetchRequest: %@", fetchRequest.description);
NSLog(@"# RECORDS TO UPDATE: %d",matchingObjectsArray.count );
結果の FetchRequest は次のとおりです。
<NSFetchRequest: 0x1f5d69d0> (entity: CaseStatusCode; predicate: ("caseStatusCodeUID" IN {"ef236614-aaa2-49ae-8713-fd4847948498"}); sortDescriptors: ((
"(caseStatusCodeUID, ascending, compare:)"
)); type: NSManagedObjectResultType; )
そして、私が言ったように、その UID を持つ caseStatusCode は存在します。また、述語を設定しない場合、すべての CaseStatusCodes を取得するので、フェッチが機能していることがわかります..述語に何かがあるだけです。
編集#2
上記ではばかげていましたが、正しい述語形式では %K を使用します。
[fetchRequest setPredicate: [NSPredicate predicateWithFormat: @"%K IN %@",uidKey, uidArray]];
編集#3
idArray と resultsArray を反復処理する最良の方法は何でしょうか? すなわち
最終的に 2 つの並べ替えられた配列が作成されます。1 つはフェッチ要求に渡された従業員 ID を含み、もう 1 つはそれらに一致する管理対象オブジェクトを含みます。それらを処理するには、次の手順に従って並べ替えられたリストをたどります。
- 次の ID と Employee を取得します。ID が従業員 ID と一致しない場合は、その ID の新しい従業員を作成します。
- 次の従業員を取得: ID が一致する場合は、次の ID と従業員に移動します。