我正在开发的应用程序必须通过 Web 服务调用与数据库保持同步。
您最初必须插入大约 300k 条记录,这需要很长时间。初次下载后,它会调用更新 Web 服务来获取所有已更改的记录。
在更新调用期间,我必须首先查看该对象是否已经存在,这确实减慢了更新过程。通常在早上有大约 5k 条记录需要更新,这几乎与插入 300k 条记录的时间一样长。
代码如下。有没有更快、更有效的方法来做到这一点?
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"]];
}
}
存在函数
+ (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 的最佳方法是什么?IE
您最终会得到两个排序的数组——一个包含传递到 fetch 请求中的员工 ID,另一个包含与它们匹配的托管对象。要处理它们,请按照以下步骤遍历排序列表:
- 获取下一个 ID 和 Employee。如果 ID 与员工 ID 不匹配,请为该 ID 创建一个新员工。
- 获取下一个员工:如果 ID 匹配,则移动到下一个 ID 和员工。