Question

Say I have JSON like this:

{
    "hits": 4056,
    "books": [
        {
            "name": "Book 1"
        },
        {
            "name": "Book 2"
        },
        {
            "name": "Book 3"
        }
    ]
}

I would like to map this response to BooksResponse object:

@interface BooksResponse
@property (nonatomic, assign) NSInteger hits;
@property (nonatomic, strong) NSArray* books;
@end

Where books property is an array of CoreData Book objects. I'm using RKObjectEntity to map BooksResponse like this:

RKObjectMapping* booksResponseMapping = [RKObjectMapping mappingForClass:[BooksResponse class]];
[booksResponseMapping addAttributeMappingsFromDictionary:@{
        @"hits" : @"hits"
}];

[booksResponseMapping addPropertyMapping:[RKRelationshipMapping
        relationshipMappingFromKeyPath:@"books"
                             toKeyPath:@"books"
                           withMapping:[self booksMapping]]];

And booksMapping is implemented like this:

RKEntityMapping* bookMapping = [RKEntityMapping mappingForEntityForName:@"Book"
                                                       inManagedObjectStore:[self managedObjectStore]];
[bookMapping addAttributeMappingsFromDictionary:@{
        @"name" : @"name"
}];

but whenever RestKit tries to perform mapping there is a crash:

CoreData: error: Failed to call designated initializer on NSManagedObject class 'Book'

I checked, during execution ManagedObjectStore exists on RKObjectManager instance. Application hangs in class RKMappingOperation:355 on line

id currentValue = [self.destinationObject valueForKeyPath:keyPath];

Is there a way one can make relationship between plain objectiveC object and NSManagedObject so that only part of JSON response is persisted in CoreData?

Was it helpful?

Solution

This is the difference between RKObjectRequestOperation and RKManagedObjectRequestOperation. Because you only have 1 response descriptor and it matches an object (not a managed object), RestKit will use RKObjectRequestOperation. When it does this, the managed object store is not available during the mapping so no managed objects can be created.

A workaround:

Instead of using 1 response descriptor, use 2. The first just creates the BooksResponse and maps the hits. The second creates the Books and maps the name.

Once the operation is complete, you will be provided with a mapping response whose dictionary contains 2 keys: null and "books". The null key holds the BooksResponse instance and the "books" key holds the Book instances. You can now update the BooksResponse instance to populate the relationship.

Note, the keys in the mapping response correspond to the key paths specified on the 2 response descriptors.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top