Question

I'm looking to get all of my Foursquare Lists into Core Data. I'd like to use Restkit to accomplish this. The structure of the /v2/users/self/lists response is:

 "response": {
    "lists": {
        "count": 8,
        "groups": [
            {
                "type": "created",
                "name": "Lists You've Created",
                "count": 6,
                "items": [
                    {
                        "id": "13250/todos",
                        "name": "My to-do list", ...
                        }
                    {
                      "id": "13251/something",
                        "name": "Some List", ...
                    },
                    {
                      "id": "13252/somethingelse",
                        "name": "Some Other List", ...
                    }
                ]
            },
            {
                "type": "followed",
                "name": "Lists You've Saved",
                "count": 1,
                "items": [
                    {
                        "id": "5105e3cae4b0e721ca7b400a",
                        "name": "Portland's Best Coffee - 2012", ...
                      }
                     {
                      ...
                    }
                ]
            }
        ]
    }

As you can see there are 2 lists under the keyPath response.lists.groups. Ultimately I'd like to merge those 2 lists into 1, but I'd be happy with getting 2 separate lists.

I've set up my mappings as follows:

RKEntityMapping* listMapping = [RKEntityMapping mappingForEntityForName:[FOFSList entityName]
                                                   inManagedObjectStore:objectManager.managedObjectStore];
[listMapping addAttributeMappingsFromDictionary:@{
                                                     @"id": @"listID",
                                                     @"title": @"name",
                                                     @"description": @"desc",
                                                     @"user": @"user",
                                                     @"following": @"following",
                                                     @"collaborative": @"collaborative",
                                                     @"canonicalUrl": @"canonicalUrl",
                                                     @"venueCount": @"venueCount",
                                                     @"visitedCount": @"visitedCount"
                                                     }];

RKDynamicMapping *dynamicMapping = [RKDynamicMapping new];
[listMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:nil
                                                                            toKeyPath:@"items"
                                                                          withMapping:dynamicMapping]];

RKResponseDescriptor *listResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:listMapping
                                                                                         method:RKRequestMethodGET
                                                                                       pathPattern:nil
                                                                                           keyPath:@"response.lists.groups"
                                                                                       statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:listResponseDescriptor];
[dynamicMapping setObjectMappingForRepresentationBlock:^RKObjectMapping *(id representation) {
    if ([[representation valueForKey:@"type"] isEqualToString:@"created"]) {
        return listMapping;
    } else if ([[representation valueForKey:@"type"] isEqualToString:@"followed"]) {
        return listMapping;
    }

    return nil;
}];

listMapping.identificationAttributes = @[ @"listID" ];

I end up with an error:

* Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ valueForUndefinedKey:]: this class is not key value coding-compliant for the key propertyMappings.'

Am I supposed to be using RKDynamicMappings? Is there some trick that I'm missing for parsing a response that is styled like this?

Was it helpful?

Solution

For those that are interested, I got a little bit creative with the RKResponseDescriptor

 RKResponseDescriptor *listResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:listMapping
                                                                                            method:RKRequestMethodGET
                                                                                       pathPattern:nil
                                                                                           keyPath:@"response.lists.groups.@distinctUnionOfArrays.items"
                                                                                       statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];

See the collection operation @distinctUinionOfArrays was ultimately what got me what I needed. It makes a union of the 2 groups arrays, then I grab the items key from each of the objects in the union of the arrays.

OTHER TIPS

At the moment the dynamic mapping is serving as a filter on the type. That's fine if it's what you want and is the correct way to achieve the filter. But, you're applying that mapping in the wrong way.

The dynamic mapping should be supplies as the mapping for the response descriptor. It analyses the incoming object and returns the appropriate mapping to apply.

You need a new, non-dynamic, mapping to handle the nested items.

Your other question about merging can't be handled during the mapping, but it could be done by adding a method to the destination class which is called with the mapped array and it merges with an existing array and pushes the merged result into the true instance variable. The mapping destination would be the method instead of the instance variable.

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