I am mapping two classes of objects with RestKit. When I do either of them by themselves, it works out perfectly fine. But when I call them together, it will crash on line 449 in RKObjectMappingOperation.m,
[destinationSet setSet:destinationObject];
With an "EXC_BAD_ACCESS" error.
Here are my two mapping methods:
- (RKObjectLoader *)saves
{
// Create an object manager and connect core data's persistent store to it
RKObjectManager *objectManager = [RKObjectManager sharedManager];
RKManagedObjectStore* objectStore = [RKManagedObjectStore objectStoreWithStoreFilename:@"Db.sqlite"];
objectManager.objectStore = objectStore;
// Define our author mapping for saved places
RKManagedObjectMapping *authorMapping = [RKManagedObjectMapping mappingForEntityWithName:@"Person"];
[authorMapping mapAttributes:@"uid", nil];
// Define our place mapping
RKManagedObjectMapping *placeMapping = [RKManagedObjectMapping mappingForEntityWithName:@"Place"];
[placeMapping mapAttributes:@"uid",@"name",@"address", nil];
// Now, connect the two via a save
RKManagedObjectMapping *saveMapping = [RKManagedObjectMapping mappingForEntityWithName:@"Save"];
[saveMapping mapAttributes:@"uid", @"timestamp", nil];
[saveMapping mapKeyPath:@"place" toRelationship:@"place" withMapping:placeMapping];
[saveMapping mapKeyPath:@"author" toRelationship:@"author" withMapping:authorMapping];
// We expect to find the place entity inside of a dictionary keyed "saves"
[objectManager.mappingProvider setMapping:saveMapping forKeyPath:@"saves"];
// Prepare our object loader to load and map objects from remote server, and send
RKObjectLoader *objectLoader = [objectManager objectLoaderWithResourcePath:@"places/saves" delegate:self];
objectLoader.method = RKRequestMethodGET;
[objectLoader send];
return objectLoader;
}
- (RKObjectLoader *)recommends
{
// Create an object manager and connect core data's persistent store to it
RKObjectManager *objectManager = [RKObjectManager sharedManager];
RKManagedObjectStore* objectStore = [RKManagedObjectStore objectStoreWithStoreFilename:@"Db.sqlite"];
objectManager.objectStore = objectStore;
// Define our author mapping for recommended places
RKManagedObjectMapping *authorMapping = [RKManagedObjectMapping mappingForEntityWithName:@"Person"];
[authorMapping mapAttributes:@"uid", nil];
// Define our place mapping
RKManagedObjectMapping *placeMapping = [RKManagedObjectMapping mappingForEntityWithName:@"Place"];
[placeMapping mapAttributes:@"uid",@"name",@"address", nil];
// Now, connect the two via a recommend
RKManagedObjectMapping *recommendMapping = [RKManagedObjectMapping mappingForEntityWithName:@"Recommend"];
[recommendMapping mapAttributes:@"uid", @"timestamp", nil];
[recommendMapping mapKeyPath:@"place" toRelationship:@"place" withMapping:placeMapping];
[recommendMapping mapKeyPath:@"author" toRelationship:@"author" withMapping:authorMapping];
// We expect to find the place entity inside of a dictionary keyed "recommends"
[objectManager.mappingProvider setMapping:recommendMapping forKeyPath:@"recommends"];
// Prepare our object loader to load and map objects from remote server, and send
RKObjectLoader *objectLoader = [objectManager objectLoaderWithResourcePath:@"places/recommends" delegate:self];
objectLoader.method = RKRequestMethodGET;
[objectLoader send];
return objectLoader;
}
When I call one, or the other, it works. When I call both,
[self saves];
[self recommends];
It crashes. Any idea why?
The call to set
objectManager.objectStoreis causing the previously setobjectStoreto be released fromobjectManager. The first call,[self saves]creates and sets anobjectStoreobject, then second call[self recommends]repeats this, thereby removing the first one set in[self saves]. Some time during the processing started off by[self saves], the original (released)objectStoreobject is being accessed, hence the crash.A potential fix would be to refactor out the
objectStoresetter into a separate method which is called by both methods, or wrap it in anif (!objectManager.objectStore) { ... }statement.