Background: I have a managed object, Car. I have a RESTful search API sitting on localhost/cars/search. The returned results are Car objects from the server side, but I only want to save the one the user chooses. The rest of the Cars I want to discard when they tap back out of Search.
At first I was all like:
@interface Car : NSManagedObject //<--- managed object
@property (nonatomic, strong) NSNumber* year;
@property (nonatomic, strong) NSString* make;
@property (nonatomic, strong) NSString* model;
@end
@interface TransientCar : NSObject //<--- regular NSObject!
@property (nonatomic, strong) NSNumber* year;
@property (nonatomic, strong) NSString* make;
@property (nonatomic, strong) NSString* model;
@end
I was mapping the REST API search results JSON into TransientCar objects for the purposes of displaying search results, but not saving them to the context. By default, if you map a managed object, RestKit will call its +object convenience factory to create the object and insert it into the current context (hard-coded to sharedManager’s object store’s context, btw!)
This seemed unsustainable. So now I’m just using NSMutableDictionary to hold the search result data until the user taps into a detail view and does something worth saving a real managed object for:
RKObjectMapping* tempCarMapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
[tempCarMapping mapKeyPathsToAttributes:
@"year", @"year",
@"make", @"make",
@"model", @"model",
nil];
Is this a good practice? Using NSMutableDictionary as a temporary representation until the user does something that warrants inserting a new object into the context? I was kind of a fan of using the original managed object subclass to represent the data, but somehow being able to flag it as “don’t keep” or something, but every time I do that I feel like I’m fighting the framework (and race conditions). I also tried using a scratch/throwaway context by creating a new RKObjectManager and just clearing its whole context afterwards, but RestKit’s ActiveRecord category’s +managedObjectContext method is hardcoded to return:
[[[RKObjectManager sharedManager] objectStore] managedObjectContext];
That sort of scuttles the possibility of ever using a scratch context for temp/trash data.
First, I’ve done this in the past using your method of having two copies of the model, one which is for Core Data and one which is transient (just an NSObject). That worked without any problems for me.
As for your other attempts, I don’t think the library forces your hand as much as you think. Look at the API for
RKManagedObjectStoreandNSManagedObject+ActiveRecord. In particular, RKManagedObjectStore has amanagedObjectContextproperty, a method- (NSManagedObjectContext*)newManagedObjectContextand several methods for merging changes.You’re right that
[NSManagedObject managedObjectContext]always returns the sharedManager’s context – but that makes sense, it’s a class method. Otherwise how would the class know which context to return? But it’s moot since there are so many other ways to create new contexts and access them. Or sidestepping that entirely, you could just keep a reference to your temporary context and use it directly.This gives you a few options: have multiple ObjectManagers, have one object manager but create a temporary context from it and only keep the objects you want, create a transient object based on the managed object.
The NSMutableDictionary option doesn’t seem as flexible as the other methods, but I wouldn’t say it’s “bad practice.”