Search code examples
iosjsonobjective-crestkit

RestKit 0.20 mapping trouble (using JSON from API)


I can pull in the springs name, but can't pull in the leafs abbreviation correctly.

Can you help? Will post any extra code as needed.

API JSON

{
    "springs": [{
        "name": "daff",
        "links": {
            "api": {
                "springs": {
                    "href": "http://api.xxx.com/v1/springs/daff"
                },
            }
        },
        "leafs": [{
            "name": "raff",
            "abbreviation": "rf",
            "season": {
                "year": 2014,
            },
        },

ViewController.m

@property (nonatomic, strong) NSArray *venues;
@property (nonatomic, strong) NSArray *venuesLeafs;

- (void)configureRestKit
{
// initialize AFNetworking HTTPClient
      NSURL *baseURL = [NSURL URLWithString:@"https://api.xxx.com"];
      AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:baseURL];
      
      // initialize RestKit
      RKObjectManager *objectManager = [[RKObjectManager alloc] initWithHTTPClient:client];
      
      // setup object mappings
      RKObjectMapping *venueMapping = [RKObjectMapping mappingForClass:[Venue class]];
      [venueMapping addAttributeMappingsFromArray:@[@"name"]];

      RKObjectMapping *venuevenueMapping = [RKObjectMapping mappingForClass:[VenueVenue class]];
      [venuevenueMapping addAttributeMappingsFromDictionary:@{@"abbreviation": @"abbreviation"}]; 
      
      [venueMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"abbreviation" toKeyPath:@"abbreviation" withMapping:venuevenueMapping]];
      
      // register mappings with the provider using a response descriptor
      RKResponseDescriptor *responseDescriptor =
      [RKResponseDescriptor responseDescriptorWithMapping:venueMapping
                                                   method:RKRequestMethodGET
                                              pathPattern:nil
                                                  keyPath:@"springs"  
                                              statusCodes:[NSIndexSet indexSetWithIndex:200]];
      
      
          [objectManager addResponseDescriptor:responseDescriptor];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
      return venues.count;
}


- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
      Venue *venue = [venues objectAtIndex:section];
      return venue.name;
}


    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        static NSString *CellIdentifier = @"standardCell";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
Venue *venue = [venues objectAtIndex:indexPath.section];
          VenueVenue *venuevenue = [venuesLeafs objectAtIndex:indexPath.row];
          cell.textLabel.text = venuevenue.abbreviation;
        
        return cell;
    }

Seems to not be adding the property mapping to abbreviation correctly.

UPDATE: Adding headers per request

Venue.h

#import "VenueVenue.h"

@interface Venue : NSObject

@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) VenueVenue *venueVenue;
@property (nonatomic, strong) NSArray *leagues;

@end

VenueVenue.h

@interface VenueVenue : NSObject

@property (nonatomic, strong) NSString *abbreviation;

@end

Solution

  • Change

    relationshipMappingFromKeyPath:@"abbreviation" toKeyPath:@"abbreviation"
    

    to

    relationshipMappingFromKeyPath:@"leafs" toKeyPath:@"venueVenues"
    

    Because the array content in the response that equates to your desired relationship content is under the 'leafs' key, not the inner 'abbreviation' key.

    And change this

    @property (nonatomic, strong) VenueVenue *venueVenue;
    

    to

    @property (nonatomic, strong) NSMutableArray *venueVenues;
    

    For your table view I expect something like:

    You should have an array of venues. The number of sections should be the count of venues.

    For each section, you can have a header to show the venue details and the number of rows is the count of venues.venueVenues (though you should really rename the VenueVenue class and property name).

    In the delegate methods you get the venue with venue = self.venues[indexPath.section] and then, for the rows, venueVenue = venue.venueVenues[indexPath.row]