Reputation: 3115
I'm new to CoreData and Restkit, and I'm having a lot of trouble with the following error.
I'm using restkit to parse some venues returned from Foursquare. Unfortunately I keep getting this error:
2013-07-12 16:12:46.369 FlokMobile[5903:c07] CoreData: error: Serious application error. Exception was caught during Core Data change processing. This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification. [<FoursquareVenue 0x1ec5fb00> valueForUndefinedKey:]: the entity Venue is not key value coding-compliant for the key "distance". with userInfo {
NSTargetObjectUserInfoKey = "<FoursquareVenue: 0x1ec5fb00> (entity: Venue; id: 0xb472c10 <x-coredata://EAB387D9-C6CB-4873-84C5-1C32E137FFE9/Venue/p49> ; data: {\n canonicalUrl = \"https://foursquare.com/v/sams-cable-car-lounge/5171ef7b498e4035a7f7a371\";\n location = \"0xb477860 <x-coredata://EAB387D9-C6CB-4873-84C5-1C32E137FFE9/Location/p30>\";\n name = \"Sam's Cable Car Lounge\";\n venueID = 5171ef7b498e4035a7f7a371;\n})";
NSUnknownUserInfoKey = distance;
}
2013-07-12 16:12:46.370 FlokMobile[5903:c07] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<FoursquareVenue 0x1ec5fb00> valueForUndefinedKey:]: the entity Venue is not key value coding-compliant for the key "distance".'
*** First throw call stack:
(0x1e42012 0x1c67e7e 0x1ecafb1 0x24d1d4 0x168000b 0x1e8fc4 0x169e247 0x1738c62 0x2af8a5 0x2aa735 0x2ad011 0x17284f9 0x1e9c0c5 0x1df6efa 0x165cbb2 0x1bf163 0x258d2f 0x1ba596 0x1b9869 0x1e6558 0x25b025 0x1e0cc1 0x2697731 0x26a6014 0x26967d5 0x1de8af5 0x1de7f44 0x1de7e1b 0x28dd7e3 0x28dd668 0xbabffc 0x2e7d 0x2da5)
libc++abi.dylib: terminate called throwing an exception
Here is the code that I used to setup my key mappings:
// Setup Restkit for Foursquare
//Setup mapping for response
NSError *error = nil;
NSURL *modelURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"FoursquareModel" ofType:@"momd"]];
//mutableCopy might not be necessary
NSManagedObjectModel *managedObjectModel = [[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL] mutableCopy];
RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];
//Initialize Core Data stack
[managedObjectStore createPersistentStoreCoordinator];
NSPersistentStore __unused *persistentStore = [managedObjectStore addInMemoryPersistentStore:&error];
NSAssert(persistentStore, @"Failed to add persistent store: %@", error);
[managedObjectStore createManagedObjectContexts];
//Set default store shared instance
[RKManagedObjectStore setDefaultStore:managedObjectStore];
//Configure Object Manager
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"https://api.foursquare.com/v2/"]];
objectManager.managedObjectStore = managedObjectStore;
[RKObjectManager setSharedManager:objectManager];
RKEntityMapping *venueMapping = [RKEntityMapping mappingForEntityForName:@"Venue" inManagedObjectStore:managedObjectStore];
RKEntityMapping *locationMapping = [RKEntityMapping mappingForEntityForName:@"Location" inManagedObjectStore:managedObjectStore];
[venueMapping addAttributeMappingsFromDictionary:@{
@"name": @"name",
@"id": @"venueID",
@"canonicalUrl": @"canonicalUrl"}];
venueMapping.identificationAttributes = @[@"venueID"];
[locationMapping addAttributeMappingsFromArray:@[ @"address",@"cc",@"city",@"country",@"crossStreet",@"distance",@"lat",@"lng",
@"postalCode",@"state"]];
//[venueMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"location" toKeyPath:@"location" withMapping:locationMapping]];
[venueMapping addRelationshipMappingWithSourceKeyPath:@"response.venues.location" mapping:locationMapping];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor
responseDescriptorWithMapping:venueMapping
pathPattern:nil
keyPath:@"response.venues"
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:responseDescriptor];
And my CoreData models:
Everytime I run the app, it always fails on encoding the same key. It is able to load the venues and map the keys to the Venue entity. I believe there might be a problem with the way I'm handling the relationship between the Venue and Location entity.
Here's what the JSON that I'm getting looks like:
{
"meta" : {
"code" : 200
},
"response" : {
"venues" : [
{
"id" : "40bbc700f964a520b1001fe3",
"categories" : [
{
"pluralName" : "Plazas",
"primary" : true,
"shortName" : "Plaza",
"id" : "4bf58dd8d48988d164941735",
"name" : "Plaza",
"icon" : {
"prefix" : "https://foursquare.com/img/categories_v2/parks_outdoors/plaza_",
"suffix" : ".png"
}
}
],
"stats" : {
"checkinsCount" : 75856,
"usersCount" : 40342,
"tipCount" : 176
},
"venuePage" : {
"id" : "34303229"
},
"storeId" : "",
"contact" : {
"phone" : "4157817880",
"formattedPhone" : "(415) 781-7880",
"twitter" : "unionsquaresf"
},
"hereNow" : {
"groups" : [],
"count" : 0
},
"verified" : true,
"url" : "http://visitunionsquaresf.com",
"referralId" : "v-1373553758",
"restricted" : true,
"location" : {
"address" : "Union Square Park",
"city" : "San Francisco",
"distance" : 68,
"postalCode" : "94108",
"crossStreet" : "btwn Post, Stockton, Geary & Powell St.",
"country" : "United States",
"lat" : 37.787750172585,
"lng" : -122.40762822536455,
"state" : "CA",
"cc" : "US"
},
"canonicalUrl" : "https://foursquare.com/v/union-square/40bbc700f964a520b1001fe3",
"specials" : {
"count" : 0,
"items" : []
},
Upvotes: 1
Views: 3872
Reputation: 3115
So here's what I've figured out: Restkit, for some bizarre reason is looking for the key "distance" in the entity "venue"
"distance" is not an attribute in the JSON received from Foursquare, nor is it explicitly mapped anywhere by code.
I fixed the immediate issue temporarily by adding the "distance" key to the "venue" entity. I don't know why it works, and it might have some weird implications later on.
If anyone can shed more light on this issue, I would gladly appreciate it. Hopefully I'm doing something wrong in my code and I just don't see it!
EDIT: Even with Blake's suggestion, I was getting the same error.
Upvotes: 1
Reputation: 6617
I think you have your response descriptor and relationship mapping key paths all twisted up. You are double specifying the response.venues
key path in the descriptor and then again in a self-referential relationship mapping. Try this instead:
RKEntityMapping *venueMapping = [RKEntityMapping mappingForEntityForName:@"Venue" inManagedObjectStore:managedObjectStore];
RKEntityMapping *locationMapping = [RKEntityMapping mappingForEntityForName:@"Location" inManagedObjectStore:managedObjectStore];
[venueMapping addAttributeMappingsFromDictionary:@{
@"name": @"name",
@"id": @"venueID",
@"canonicalUrl": @"canonicalUrl"}];
venueMapping.identificationAttributes = @[@"venueID"];
[locationMapping addAttributeMappingsFromArray:@[ @"address",@"cc",@"city",@"country",@"crossStreet",@"distance",@"lat",@"lng",
@"postalCode",@"state"]];
[venueMapping addRelationshipMappingWithSourceKeyPath:@"location" mapping:locationMapping];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor
responseDescriptorWithMapping:venueMapping
pathPattern:nil
keyPath:@"response.venues"
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:responseDescriptor];
Using the logging or unit tests can make debugging your mappings much easier.
Upvotes: 0