0

我的数据模型名为“Person”,它有 3 个属性“id”、“firstName”和“lastName”

使用 AFNetworking 导入 JSON 数据时,我希望能够使用“id”作为标识符来检查实体是否已经存在于核心数据中。如果它不存在我想创建它,如果它存在我想合并或更新它。

现在我有一个名为 duplicateCheck 的方法,它看起来像:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"id==%@", _person.id];
NSFetchRequest *fetch = [[NSFetchRequest alloc] init];
NSError *error = nil;
[fetch setEntity:[NSEntityDescription entityForName:@"Person" inManagedObjectContext:self.managedObjectContext]];
[fetch setPredicate:predicate];
NSArray *items = [self.managedObjectContext executeFetchRequest:fetch error:&error];
for (NSManagedObject *object in items) {
// Not sure how to check from here and insert or update

// then save and call it during the API request?
}

我有一个谓词设置,但不知道从这里去哪里。循环遍历每个项目是正确的方式还是我要以错误的方式进行?

4

2 回答 2

0

所以我评论了一个指向我写的关于这个主题的教程的链接,但是为了缩小范围,这个方法可能会帮助你指导。

  NSManagedObjectContext *managedObjectContext = [[SDCoreDataController sharedInstance] backgroundManagedObjectContext];
    //
    // Iterate over all registered classes to sync
    //
    for (NSString *className in self.registeredClassesToSync) {
        if (![self initialSyncComplete]) { // import all downloaded data to Core Data for initial sync
            //
            // If this is the initial sync then the logic is pretty simple, you will fetch the JSON data from disk 
            // for the class of the current iteration and create new NSManagedObjects for each record
            //
            NSDictionary *JSONDictionary = [self JSONDictionaryForClassWithName:className];
            NSArray *records = [JSONDictionary objectForKey:@"results"];
            for (NSDictionary *record in records) {
                [self newManagedObjectWithClassName:className forRecord:record];
            }
        } else {
            //
            // Otherwise you need to do some more logic to determine if the record is new or has been updated. 
            // First get the downloaded records from the JSON response, verify there is at least one object in 
            // the data, and then fetch all records stored in Core Data whose objectId matches those from the JSON response.
            //
            NSArray *downloadedRecords = [self JSONDataRecordsForClass:className sortedByKey:@"objectId"];
            if ([downloadedRecords lastObject]) {
                //
                // Now you have a set of objects from the remote service and all of the matching objects 
                // (based on objectId) from your Core Data store. Iterate over all of the downloaded records 
                // from the remote service.
                //
                NSArray *storedRecords = [self managedObjectsForClass:className sortedByKey:@"objectId" usingArrayOfIds:[downloadedRecords valueForKey:@"objectId"] inArrayOfIds:YES];
                int currentIndex = 0;
                // 
                // If the number of records in your Core Data store is less than the currentIndex, you know that 
                // you have a potential match between the downloaded records and stored records because you sorted 
                // both lists by objectId, this means that an update has come in from the remote service
                //
                for (NSDictionary *record in downloadedRecords) {
                    NSManagedObject *storedManagedObject = nil;
                    if ([storedRecords count] > currentIndex) {
                        //
                        // Do a quick spot check to validate the objectIds in fact do match, if they do update the stored 
                        // object with the values received from the remote service
                        //
                        storedManagedObject = [storedRecords objectAtIndex:currentIndex];
                    }

                    if ([[storedManagedObject valueForKey:@"objectId"] isEqualToString:[record valueForKey:@"objectId"]]) {
                        //
                        // Otherwise you have a new object coming in from your remote service so create a new 
                        // NSManagedObject to represent this remote object locally
                        //
                        [self updateManagedObject:[storedRecords objectAtIndex:currentIndex] withRecord:record];
                    } else {
                        [self newManagedObjectWithClassName:className forRecord:record];
                    }
                    currentIndex++;
                }
            }
        }
        //
        // Once all NSManagedObjects are created in your context you can save the context to persist the objects 
        // to your persistent store. In this case though you used an NSManagedObjectContext who has a parent context 
        // so all changes will be pushed to the parent context
        //
        [managedObjectContext performBlockAndWait:^{
            NSError *error = nil;
            if (![managedObjectContext save:&error]) {
                NSLog(@"Unable to save context for class %@", className);
            }
        }];

        //
        // You are now done with the downloaded JSON responses so you can delete them to clean up after yourself, 
        // then call your -executeSyncCompletedOperations to save off your master context and set the 
        // syncInProgress flag to NO
        //
        [self deleteJSONDataRecordsForClassWithName:className];
        [self executeSyncCompletedOperations];
    }
}
于 2013-05-14T19:10:17.213 回答
0

通常人们会期望标识符是唯一的。因此如果谓词返回 0 个对象,你就知道这个对象是新的。如果返回 1,您就知道该对象已经存在,也许您需要更新它。

NSArray *items = [self.managedObjectContext executeFetchRequest:fetch error:&error];
if(items){ 
    if([items count] == 0){
        //the object is not present yet. create it.
    } else if([items count] == 1) {
        NSManageObject *obj = items[0];
        //there is exactly 1 object. change it properties if needed 
    } else {
        //what to do if several objects have the same identifier???
    }
} else {
    //handle error from the error object
}
于 2013-05-14T18:23:14.420 回答