Search code examples
iosrestkitfoursquarerestkit-0.20

RestKit - Mapping Entities with CoreData - Response Error


I'm building an iOS app that needs to implement search results from Foursquare. I'm using RestKit, but keep running into the same error: "no response descriptors match the response loaded"

Here's the relevant portion of my code:

    RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"https://api.foursquare.com/v2"]];
objectManager.managedObjectStore = managedObjectStore;

[RKObjectManager setSharedManager:objectManager];

RKEntityMapping *entityMapping = [RKEntityMapping mappingForEntityForName:@"Venue" inManagedObjectStore:managedObjectStore];
[entityMapping addAttributeMappingsFromDictionary:@{
 @"name":         @"name",
 @"id":           @"id",
 @"canonicalUrl": @"canonicalUrl"}];
entityMapping.identificationAttributes = @[@"id"];

RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor
                                            responseDescriptorWithMapping:entityMapping
                                            pathPattern:@"/v2/venues/search"
                                            keyPath:nil
                                            statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];

[objectManager addResponseDescriptor:responseDescriptor];

//Create strings for auth
clientID = [NSString stringWithUTF8String:kCLIENTID];
clientSecret = [NSString stringWithUTF8String:kCLIENTSECRET];

[self loadVenues];

loadVenues Method:

    NSString *currentLatLon = [NSString stringWithFormat:@"%1$f,%2$f", locationManager.location.coordinate.latitude, locationManager.location.coordinate.longitude];
NSDictionary *queryParams = [NSDictionary dictionaryWithObjectsAndKeys:
                             @"20130601",@"v",
                             currentLatLon,@"ll",
                             clientID,@"client_id",
                             clientSecret,@"client_secret", nil];
[[RKObjectManager sharedManager]
getObjectsAtPath:@"https://api.foursquare.com/v2/venues/search"
parameters:queryParams
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
    //Do something
    }
failure:^(RKObjectRequestOperation *operation, NSError *error) {
    //Do something else
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"An Error Has Occurred" message:[error localizedDescription] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [alertView show];
}];

Core Data Model: enter image description here enter image description here

And here's the kind of JSON data that I'm trying to parse:

representation: {
meta =     {
    code = 200;
};
response =     {
    venues =         (
                    {
            canonicalUrl = "https://foursquare.com/v/union-square/40bbc700f964a520b1001fe3";
            categories =                 (
                                    {
                    icon =                         {
                        prefix = "https://foursquare.com/img/categories_v2/parks_outdoors/plaza_";
                        suffix = ".png";
                    };
                    id = 4bf58dd8d48988d164941735;
                    name = Plaza;
                    pluralName = Plazas;
                    primary = 1;
                    shortName = "Plaza / Square";
                }
            );
            contact =                 {
                formattedPhone = "(415) 781-7880";
                phone = 4157817880;
                twitter = unionsquaresf;
            };
            hereNow =                 {
                count = 8;
                groups =                     (
                                            {
                        count = 8;
                        items =                             (
                        );
                        name = "Other people here";
                        type = others;
                    }
                );
            };
            id = 40bbc700f964a520b1001fe3;
            location =                 {
                address = "Union Square Park";
                cc = US;
                city = "San Francisco";
                country = "United States";
                crossStreet = "btwn Post, Stockton, Geary & Powell St.";
                distance = 68;
                lat = "37.787750172585";
                lng = "-122.4076282253645";
                postalCode = 94108;
                state = CA;
            };
            name = "Union Square";
            referralId = "v-1370991275";
            restricted = 1;
            specials =                 {
                count = 0;
                items =                     (
                );
            };
            stats =                 {
                checkinsCount = 73242;
                tipCount = 172;
                usersCount = 39007;
            };
            url = "http://visitunionsquaresf.com";
            venuePage =                 {
                id = 34303229;
            };
            verified = 1;
        },

Solution

  • Here's what I've figured out after looking at Wain's suggestion.

    At runtime RestKit couldn't find my responseDescriptor. Here's what I changed to get my responseDescriptor recognized:

    RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor
                                                responseDescriptorWithMapping:entityMapping
                                                pathPattern:nil
                                                keyPath:@"response.venues"
                                                statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
    

    After changing that and making sure that I was using the right paths (always double check your paths!), I noticed that my keys weren't being mapped properly.

    The problem is that I named one of my keys "id" in the entity model. "id" is a system keyword and caused a whole slew of funky compiler errors.

    I just had to go back to my data model and adjust my Attributes.

        RKEntityMapping *entityMapping = [RKEntityMapping mappingForEntityForName:@"Venue" inManagedObjectStore:managedObjectStore];
    [entityMapping addAttributeMappingsFromDictionary:@{
     @"name":         @"name",
     @"id":           @"venueID",
     @"canonicalUrl": @"canonicalUrl"}];
    entityMapping.identificationAttributes = @[@"venueID"];