我的数据模型名为“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?
}
我有一个谓词设置但不知道从哪里开始。是以正确的方式循环每个项目还是以错误的方式解决这个问题?
答案 0 :(得分: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
}
答案 1 :(得分:0)
所以我用link评论了我在这个主题上写的教程,但为了缩小范围,这个方法可能有助于指导你。
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];
}
}