此代码如何仅使用核心数据更新?

时间:2013-04-26 23:22:49

标签: ios core-data

这是来自RW教程的SyncEngine。我需要帮助了解如何只获取Web上的UPDATED记录并将其处理为Core Data。

- (void)processJSONDataRecordsIntoCoreData {
    NSManagedObjectContext *managedObjectContext = [[SDCoreDataController sharedInstance] backgroundManagedObjectContext];
    // Iterate over all registered classes --- CHECK!
    for (NSString *className in self.registeredClassesToSync) {
        if (![self initialSyncComplete]) { 
            NSDictionary *JSONDictionary = [self JSONDictionaryForClassWithName:className];
            NSArray *records = [JSONDictionary objectForKey:@"results"];
            for (NSDictionary *record in records) {
                [self newManagedObjectWithClassName:className forRecord:record];
            }
        } else {
            NSArray *downloadedRecords = [self JSONDataRecordsForClass:className sortedByKey:@"objectId"];
            if ([downloadedRecords lastObject]) {
                 NSArray *storedRecords = [self managedObjectsForClass:className sortedByKey:@"objectId" usingArrayOfIds:[downloadedRecords valueForKey:@"objectId"] inArrayOfIds:YES];
                int currentIndex = 0;
                //if dl count is < current index, there is an updated object dl from the web
                for (NSDictionary *record in downloadedRecords) {
                    NSManagedObject *storedManagedObject = nil;
                    //Quick check to see if they indeed match, if they do, update the stored object with remote service objects
                    if ([storedRecords count] > currentIndex) {
                        storedManagedObject = [storedRecords objectAtIndex:currentIndex];
                    }
                    //Othwerwise its a new object and you need to create a new NSManagedObject to represent it in CDdb
                    if ([[storedManagedObject valueForKey:@"objectId"] isEqualToString:[record valueForKey:@"objectId"]]) {
                        [self updateManagedObject:[storedRecords objectAtIndex:currentIndex] withRecord:record];
                    } else {
                        [self newManagedObjectWithClassName:className forRecord:record];
                    }
                    currentIndex++;
                }
            }
        }
        // After all NSMO are created in your context, save it!
        [managedObjectContext performBlockAndWait:^{
            NSError *error = nil;
            if (![managedObjectContext save:&error]) {
                NSLog(@"Unable to save context for class %@", className);
            }
        }];
        // Cleanup time
        [self deleteJSONDataRecordsForClassWithName:className];
        [self executeSyncCompletedOperations];
    }

   [self downloadDataForRegisteredObjects:NO];
}

根据我的理解,在第一次或初始同步时,它会获取JSONDictionaryForClassWithName,它从磁盘读取下载的数据并创建newManagedObjectWithClassName。

我的困惑在于更新else块。 downloadedRecords是从JSONDataRecordsForClass填充的,它只调用JSONDictionaryForClassWithName。然后它检查该数组中是否至少有一个对象。如果它有这样做:

NSArray *storedRecords = [self managedObjectsForClass:className sortedByKey:@"objectId" usingArrayOfIds:[downloadedRecords valueForKey:@"objectId"] inArrayOfIds:YES];

这将获取所有managedObjectsForClass:sortedByKey,它位于:

- (NSArray *)managedObjectsForClass:(NSString *)className sortedByKey:(NSString *)key usingArrayOfIds:(NSArray *)idArray inArrayOfIds:(BOOL)inIds {
    __block NSArray *results = nil;
    NSManagedObjectContext *managedObjectContext = [[SDCoreDataController sharedInstance] backgroundManagedObjectContext];
    NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:className];
    NSPredicate *predicate;
    if (inIds) {
        predicate = [NSPredicate predicateWithFormat:@"objectId IN %@", idArray];
    } else {
        predicate = [NSPredicate predicateWithFormat:@"NOT (objectId IN %@)", idArray];
    }

    [fetchRequest setPredicate:predicate];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:
                                      [NSSortDescriptor sortDescriptorWithKey:@"objectId" ascending:YES]]];
    [managedObjectContext performBlockAndWait:^{
        NSError *error = nil;
        results = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
    }];

    return results;
}

比较[storedRecords count]&gt;的下一位currentIndex令人困惑。有人可以解释一下吗?我认为我的困惑在于managedObjectsForClass方法对usingArraysOfIds&amp; inArrayOfIds。

我希望在某些时候它从下载的记录中获取updatedAt字段,并将其与CoreData提取的记录的updatedAt字段进行比较。

1 个答案:

答案 0 :(得分:0)

此函数正在处理存储的JSON。实际的远程提取和updateAt检查发生在downloadDataForRegisteredObjectsmostRecentUpdatedAtDateForEntityWithName

[storedRecords count] > currentIndex有点疯狂。虽然在为原始程序员辩护时,编写任何体面的syncengine都会很快让你去googoo。基本上,他需要确定哪些记录存在,哪些记录是新的,并相应地更新本地数据存储,这就是全部。


我又看了一眼,这段代码实际上非常糟糕。它只有在本地和远程具有相同记录时才有效。或者,如果新对象具有objectId,该对象在本地商店具有的最后一个对象之后排序。 Parse objectId的情况并非如此。

如果您只使用一个设备进行测试,则可以使用,因为在推送到服务器之前,新对象将在本地插入。因此,您将始终拥有相同数量的记录。如果以其他任何方式插入其他记录,此代码将做奇怪的事情。