CoreData: API proposal - AGEntityMapperBackground
Mapping JSON representations to a "rich" domain model in ObjC is a bit
cumbersome <
http://matthiaswessendorf.wordpress.com/2012/11/19/objc-json/>.
Similar is true when mapping a JSON data/response to a NSMangedObject (and
vise versa). There is a base framework for "remote persistence", via the
CoreData API, by leveraging a custom NSIncrementalStore ->
AFIncrementalStore <
https://github.com/AFNetworking/AFIncrementalStore>.
For that,... a similar *two-way-mapping* is required, as described
here<http://matthiaswessendorf.wordpress.com/2013/01/02/coredata-data-...
.
AeroGear and CoreData
Our CoreData offerings are leveraging the AFIncrementalStore, therefore (as
with other frameworks/libraries) we need a mapping as well. We need to know
the name of the entity and we need a NSDictionary that covers the actual
JSON/property mapping. It could be done with the vanialla ObjC classes:
// some mappers:NSDictionary *task_mapper =
[NSDictionary
dictionaryWithObjectsAndKeys:@"description",@"desc",@"id",@"myId",
nil];NSDictionary *project_mapper =
[NSDictionary dictionaryWithObjectsAndKeys:@"id",@"myId", nil];
// create a schema out of the mappers:NSDictionary *schema =
[NSDictionary dictionaryWithObjectsAndKeys:task_mapper, @"Task",
project_mapper, @"Project", nil];
// pass the schema to the AGCoreDataHelper class, when doing the init...
Proposal for a custom API
I'd like to introduce a new wrapper type, called AGEntityMapper:
@interface AGEnityMapper : NSObject
@property NSString *name;@property NSDictionary *mapper;
-(id) initWithName:(NSString *) name mapper:(NSDictionary *) mapper;@end
This AGEntityMapper would be applied onto the AGCoreDataConfig:
@protocol AGCoreDataConfig <NSObject>
@property (strong, nonatomic) NSManagedObjectModel
*managedObjectModel;@property (strong, nonatomic) NSURL *baseURL;
-(void)applyEntityMappers:(AGEnityMapper *)firstObject, ...
NS_REQUIRES_NIL_TERMINATION;
@end
The actual code, would look like this:
EnityMapper *taskMapper =
[[EnityMapper alloc] initWithName:@"Task"
// mapping the properties on the "entity" (NSManagedObject)
// to the external representation (e.g. JSON)
mapper:@{ @"desc": @"description",
@"myId": @"id"}];
EnityMapper *projectMapper =
[[EnityMapper alloc] initWithName:@"Project"
// mapping the properties on the "entity" (NSManagedObject)
// to the external representation (e.g. JSON)
mapper:@{ @"myId": @"id"}];
AGCoreDataHelper *helper = [[AGCoreDataHelper alloc]
initWithConfig:^(id<AGCoreDataConfig> config) {
[config setBaseURL:[NSURL URLWithString:@"http://server.com"]];
[config applyEntityMappers:
taskMapper,
projectMapper,
nil // terminate the varargs.
];}];
--
Matthias Wessendorf
blog:
http://matthiaswessendorf.wordpress.com/
sessions:
http://www.slideshare.net/mwessendorf
twitter:
http://twitter.com/mwessendorf