I have a list of places from a rails application that I am trying to import into an iOS5 application. Each place has a parent, which is the place itself.
I am trying to import JSON data using Core Data using a dictionary
- (void)initWithDictionary:(NSDictionary *)dictionary { self.placeId = [dictionary valueForKey:@"id"]; id parent = [dictionary objectForKey:@"parent"]; if (parent && parent != [NSNull null]) { NSDictionary *parentDictionary = parent; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"placeId = %@", [parentDictionary objectForKey:@"id"]]; NSArray *matching = fetchedWithPredicate(@"Place", self.managedObjectContext, predicate, nil); if ([matching count] > 0) { self.parent = [matching objectAtIndex:0]; } else { self.parent = [NSEntityDescription insertNewObjectForEntityForName:@"Place" inManagedObjectContext:self.managedObjectContext]; [self.parent initWithDictionary:parentDictionary]; } } }
fetchedWithPredicate is a method defined as such
NSArray* fetchedWithPredicate(NSString *entityName, NSManagedObjectContext *context, NSPredicate *predicate, NSError **error) { NSFetchRequest *request = [[NSFetchRequest alloc] init]; [request setIncludesPendingChanges:YES]; NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:context]; [request setEntity:entity]; [request setPredicate:predicate]; NSArray *result = [context executeFetchRequest:request error:error]; return result; }
I also have a validation method in Place.m to make sure that I am not creating an ID for placement with the same place (placeId is the server-side identifier).
- (BOOL)validatePlaceId:(id *)value error:(NSError **)error { if (*value == nil) return YES; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"placeId = %@ AND (NOT self IN %@)", *value, [NSArray arrayWithObject:self]]; NSArray *matching = fetchedWithPredicate(@"Place", self.managedObjectContext, predicate, error); if ([matching count] > 0) { return NO; } else { return YES; } }
To import data, I retrieve all the places from the server returned in JSON format. Each place has its own information, as well as a node child with parent information, which means that each parent of several children will be displayed several times. He looks like
{ "id": 73, "name": "Some place", "parent": { "id": 2, "name": "Parent name"} }
I thought that the code above that pretends to βfind or createβ, with fetching, including unsaved changes, would be okay. But he is still trying to create some records for some places (and since then there is no validation). Looking deeper, it really inserts different main data objects for the same place ID (different pointers), but I don't know why.
thanks