RestKit 0.20 — CoreData: error: Failed to call designated initializer on NSManagedObject class
Asked Answered
B

2

19

I ran into a new problem that I can't seem to find a way around... Here is my RestKit code, following the Twitter Core Data example:

//
// RESTKIT
//

// restkit object manager
NSString *baseURL = @"http://test1.website.com";
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:baseURL]];

// enable activity indicator
[AFNetworkActivityIndicatorManager sharedManager].enabled = YES;

// managed object model
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"AppName" withExtension:@"momd"];
NSManagedObjectModel *managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
// NSLog(@"managed object model: %@", managedObjectModel);

// managed object store
RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];
objectManager.managedObjectStore = managedObjectStore;
// NSLog(@"managed object store: %@", managedObjectStore);

// persistent store
NSError *error;
NSString *storePath = [RKApplicationDataDirectory() stringByAppendingPathComponent:@"AppName.sqlite"];
NSPersistentStore *persistentStore = [managedObjectStore addSQLitePersistentStoreAtPath:storePath fromSeedDatabaseAtPath:nil withConfiguration:nil options:nil error:&error];
if (error) {
    NSLog(@"unresolved error %@, %@", error, [error userInfo]);
    abort();
}
// NSLog(@"persistent store coordinator: %@", managedObjectStore.persistentStoreCoordinator);
// NSLog(@"persistent store: %@", persistentStore);

// managed object contexts
[managedObjectStore createManagedObjectContexts];
// NSLog(@"managed object context: %@", managedObjectStore.mainQueueManagedObjectContext);

// managed object cache
managedObjectStore.managedObjectCache = [[RKInMemoryManagedObjectCache alloc] initWithManagedObjectContext:managedObjectStore.mainQueueManagedObjectContext];
// NSLog(@"mangaged object cache: %@", managedObjectStore.managedObjectCache);

//
// entity mapping
//

// album entity mapping
RKEntityMapping *albumEntityMapping = [RKEntityMapping mappingForEntityForName:@"Album" inManagedObjectStore:managedObjectStore];
albumEntityMapping.identificationAttributes = @[ @"identifier" ];
[albumEntityMapping addAttributeMappingsFromDictionary:@{ @"title" : @"title" }];

//
// response descriptor
//

// album response descriptor
[objectManager addResponseDescriptor:[RKResponseDescriptor responseDescriptorWithMapping:albumEntityMapping pathPattern:[NSString stringWithFormat:@"/albums/display/%@/%@", userInfo[@"userID"], userInfo[@"apiKey"]] keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]];

I'm requesting the information from the API via a UITableViewController class:

- (void)loadObjectsFromResourcePath:(NSString *)resourcePath;
{
   [[RKObjectManager sharedManager] getObjectsAtPath:resourcePath parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
        NSLog(@"mapping result: %@", [mappingResult array]);
        [self stopLoading];
    } failure:^(RKObjectRequestOperation *operation, NSError *error) {
        NSLog(@"error: %@", error);
        [self stopLoading];
    }];
}

However, with this code I get the following errors:

2012-12-05 17:08:14.830 AppName Alpha[1310:907] I restkit:RKLog.m:34 RestKit logging initialized...
2012-12-05 17:08:15.107 AppName Alpha[1310:907] resource path: albums/display/102/drrrbSAt6RFLsgHaKiiB6kBIyYRyzxLYinL84Kba
2012-12-05 17:08:15.113 AppName Alpha[1310:907] I restkit.support:RKMIMETypeSerialization.m:115 JSON Serialization class 'RKNSJSONSerialization' detected: Registering for MIME Type 'application/json
2012-12-05 17:08:15.118 AppName Alpha[1310:1603] I restkit.network:RKHTTPRequestOperation.m:141 GET 'http://test1.AppName.com/albums/display/102/drrrbSAt6RFLsgHaKiiB6kBIyYRyzxLYinL84Kba'
2012-12-05 17:08:15.122 AppName Alpha[1310:907] error (null), (null)
2012-12-05 17:08:35.333 AppName Alpha[1310:3e13] I restkit.network:RKHTTPRequestOperation.m:158 GET 'http://test1.AppName.com/albums/display/102/drrrbSAt6RFLsgHaKiiB6kBIyYRyzxLYinL84Kba' (200)
2012-12-05 17:08:35.351 AppName Alpha[1310:1507] CoreData: error: Failed to call designated initializer on NSManagedObject class 'AppName Album' 
2012-12-05 17:08:35.355 AppName Alpha[1310:1507] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<AppName 0x1c579380> valueForUndefinedKey:]: the entity (null) is not key value coding-compliant for the key "Title".'
*** First throw call stack:
(0x39e503e7 0x38ea9963 0x39e500d5 0x371f8d81 0x3276cc1d 0xbf545 0xc00f5 0xc0ab9 0xc44c5 0x32791299 0xb738b 0xb6e5f 0xb7ca5 0xb8343 0xb895b 0x32791299 0xf96ef 0xf8c4b 0x32791299 0x328097f7 0x32c38793 0x32c3c657 0x32c3c7d9 0x3312a7f1 0x3312a684)
libc++abi.dylib: terminate called throwing an exception

You can take a peak at the returned JSON object here: http://test1.AppName.com/albums/display/102/drrrbSAt6RFLsgHaKiiB6kBIyYRyzxLYinL84Kba

Blare answered 5/12, 2012 at 23:12 Comment(0)
L
48

This indicates that an attempt was made to create an object without calling the appropriate Core Data initializer, which probably means that you are getting an RKObjectRequestOperation instance instead of an RKManagedObjectRequestOperation.

I suspect that the response descriptor is failing to match against the URL, which is causing it to select the wrong object request operation type. You can check this by putting a breakpoint in appropriateObjectRequestOperationWithObject:method:path:parameters: at the lines that read:

NSArray *matchingDescriptors = RKFilteredArrayOfResponseDescriptorsMatchingPath(self.responseDescriptors, requestPath);
BOOL containsEntityMapping = RKDoesArrayOfResponseDescriptorsContainEntityMapping(matchingDescriptors);
BOOL isManagedObjectRequestOperation = (containsEntityMapping || [object isKindOfClass:[NSManagedObject class]]);

This logic is what's responsible for selecting the type of operation created. Check that the matchingDescriptors contains the response descriptor you are expecting and then check the values of the next two booleans. My guess is that RKFilteredArrayOfResponseDescriptorsMatchingPath is not returning what you expect.

Ladanum answered 5/12, 2012 at 23:22 Comment(9)
what class is this? also, what is returning error(null, null) on the first GET request. Also, why are there two request going out? :)Blare
appropriateObjectRequestOperationWithObject:method:path:parameters: is on RKObjectManager. Note that there are not 2 requests going out. The first log message is for the send and the second, which includes the (200) is on the response. That 'error(null, null)' message is coming from the NSLog in your failure completion block.Ladanum
I forced a RKManagedObjectRequestOperation operation for now and it's working. I'll have to backtrack tomorrow to see what the root of the problem is. The error(null, null) is not coming from me. I commented out the block even to double check.Blare
For whatever it's worth, this was helpful for me with what seemed like the same problem (CoreData+RestKit, fetching objects like above). I was able to fix it because of this description for debugging. Thanks! My bug was actually with two many '/' in once circumstance.Dogeatdog
I have significantly improved the error output when the response descriptors fail to match. If you log out the NSError returned for a failed mapping, the NSLocalizedFailureReasonErrorKey now contains a thorough summary of how the matching failed.Ladanum
New question @BlakeWatters, everything works as expected when /articles (Articles are mapped and put into CoreData), but a GET for /articles/1 has the exact same problem again. I walked through as indicated above. When I set breakpoints (starting at) 398 of RKObjectManager.m I can find it has matching descriptors. But I notice that after line 405, the managedObjectContext is nil so the 'if' condition on line 407 fails. (RESTKit 0.20.0pre4).Dogeatdog
This debugging step has allowed me to move on after being stuck for days. Thanks andy9d for your comment. I saw that there was not a "/" in my events.json. adding one allowed my GET to come back with a 200 OK. Now on to debugging the mapping.Diaz
I'd like to add that this error can also occur if you initialize a RKResponseDescriptor with a RKObjectMapping instead of RKEntityMapping. I was blindly following tutorials and not realizing that I didn't have to create a separate RKObjectMapping for my request and response descriptors.Mons
To echo many others above, this occurred when the path on the RKResponseDescriptor didn't match. The URL is something like /abc/objects but I was only including `/objects' in the descriptor. Thanks!!Buhrstone
S
1

Have now read class documentation for RKObjectManager which clarifies handling of AF networking handling of base url. If I had read this first would have saved myself some time, and also from making irrelevant comments regarding paths in RestKit examples.

Had problems matching a mix of object and entity mappings including a number of object mappings with a nil key path and different URL and found this answer very useful for determining the cause of the problem described following which may have contributed to others experiencing similar problems.

Sylvanite answered 8/12, 2013 at 10:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.