1

我正在开发的应用程序必须通过 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,另一个包含与它们匹配的托管对象。要处理它们,请按照以下步骤遍历排序列表:

  1. 获取下一个 ID 和 Employee。如果 ID 与员工 ID 不匹配,请为该 ID 创建一个新员工。
  2. 获取下一个员工:如果 ID 匹配,则移动到下一个 ID 和员工。
4

2 回答 2

2

我建议阅读这篇“有效地实现查找或创建”,这听起来像是您正在使用的领域。

于 2013-07-25T13:13:39.433 回答
1

Consider looping through all of your JSON objects to gather all of the CaseStatusCodeUID s and then fetch those in a single fetch request.

[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"caseStatusCodeUID IN[cd] %@", uidArray]];

Then loop through the result.

于 2013-07-25T13:19:30.210 回答