Saturday, 26 January 2013

[iOS] RestKit Tutorial Code For Version 0.20

I was trying to follow the RestKit tutorial at

RayWenderlich's Intro to RestKit Tutorial

but encountered various problems due to significant changes in the version 0.20 RestKit.

After searching for solutions at stackoverflow as well as RestKit.org, I finally found the missing pieces and got the example code working with RestKit version 0.20.

Firstly, after adding "#import <RestKit/RestKit.h>" in AppDelegate.m, there was a missing header file error when compiling the app. I found the solution here in stackoverflow.

To resolve this, I need to pull in additional files by running the command below in RestKit directory:

git submodule update --init --recursive

The following is code I used in MasterViewController. You should be able to reuse the other code found in RayWenderlich's tutorial for Location.m, Location.m, Venue.m, and Venue.h.

One key resource that help me was the wiki entry for RKObjectMapping at Restkit.org below:

https://github.com/RestKit/RestKit/wiki/Object-mapping

 //  
 // MasterViewController.m  
 // CoffeeShop  
 //  
 //  
 // Copyright (c) 2013 uihelpers. All rights reserved.  
 //  
 #import "MasterViewController.h"  
 #import <RestKit/RestKit.h>  
 #import "Venue.h"  
 #import "Location.h"  
 #define kCLIENTID "REPLACE_WITH_OWN_ID"  
 #define kCLIENTSECRET "REPLACE_WITH_OWN_SECRET"  
 @interface MasterViewController () {  
   NSMutableArray *_objects;  
   NSArray *cafeArray;  
 }  
 @end  
 @implementation MasterViewController  
 - (void)awakeFromNib  
 {  
   [super awakeFromNib];  
 }  
 - (void)viewDidLoad  
 {  
   [super viewDidLoad];  
      // Do any additional setup after loading the view, typically from a nib.  
   self.navigationItem.leftBarButtonItem = self.editButtonItem;  
   UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(insertNewObject:)];  
   self.navigationItem.rightBarButtonItem = addButton;  
   NSURL *baseURL = [NSURL URLWithString:@"https://api.foursquare.com/v2"];  
   AFHTTPClient * client = [AFHTTPClient clientWithBaseURL:baseURL];  
   [client setDefaultHeader:@"Accept" value:RKMIMETypeJSON];  
   RKObjectManager *objectManager = [[RKObjectManager alloc] initWithHTTPClient:client];  
   RKObjectMapping *venueMapping = [RKObjectMapping mappingForClass:[Venue class]];  
   [venueMapping addAttributeMappingsFromDictionary:@{  
    @"name" : @"name"  
    }];  
   RKObjectMapping *locationMapping = [RKObjectMapping mappingForClass:[Location class]];  
   [locationMapping addAttributeMappingsFromDictionary:@{ @"address": @"address", @"city": @"city", @"country": @"country", @"crossStreet": @"crossStreet", @"postalCode": @"postalCode", @"state": @"state", @"distance": @"distance", @"lat": @"lat", @"lng": @"lng"}];  
   /*[venueMapping mapRelationship:@"location" withMapping:locationMapping];  
   [objectManager.mappingProvider setMapping:locationMapping forKeyPath:@"location"];*/  
   [venueMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"location" toKeyPath:@"location" withMapping:locationMapping]];  
   RKResponseDescriptor * responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:venueMapping  
                                           pathPattern:nil  
                                           keyPath:@"response.venues"  
                                           statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];  
   [objectManager addResponseDescriptor:responseDescriptor];  
   NSString *latLon = @"37.33,-122.03";  
   NSString *clientID = [NSString stringWithUTF8String:kCLIENTID];  
   NSString *clientSecret = [NSString stringWithUTF8String:kCLIENTSECRET];  
   NSDictionary *queryParams;  
   queryParams = [NSDictionary dictionaryWithObjectsAndKeys:latLon, @"ll", clientID, @"client_id", clientSecret, @"client_secret", @"coffee", @"query", @"20120602", @"v", nil];  
   [objectManager getObjectsAtPath:@"https://api.foursquare.com/v2/venues/search"  
              parameters:queryParams  
               success:^(RKObjectRequestOperation * operaton, RKMappingResult *mappingResult)  
    {  
      //NSLog(@"success: mappings: %@", mappingResult);  
      NSArray *result = [mappingResult array];  
      cafeArray = [mappingResult array];  
      for (Venue *item in result) {  
        NSLog(@"name=%@",item.name);  
        NSLog(@"name=%@",item.location.distance);  
      }  
      [self.tableView reloadData];  
    }  
               failure:^(RKObjectRequestOperation * operaton, NSError * error)  
    {  
      NSLog (@"failure: operation: %@ \n\nerror: %@", operaton, error);  
    }];  
 }  
 - (void)viewDidUnload  
 {  
   [super viewDidUnload];  
   // Release any retained subviews of the main view.  
 }  
 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation  
 {  
   return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);  
 }  
 - (void)insertNewObject:(id)sender  
 {  
   if (!_objects) {  
     _objects = [[NSMutableArray alloc] init];  
   }  
   [_objects insertObject:[NSDate date] atIndex:0];  
   NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];  
   [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];  
 }  
 #pragma mark - Table View  
 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView  
 {  
   return 1;  
 }  
 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section  
 {  
   return cafeArray.count;  
 }  
 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath  
 {  
   UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];  
   /*NSDate *object = [_objects objectAtIndex:indexPath.row];  
   cell.textLabel.text = [object description];*/  
   Venue *venueObject = [cafeArray objectAtIndex: indexPath.row];  
   cell.textLabel.text = [venueObject.name length] > 24 ? [venueObject.name substringToIndex:24] : venueObject.name;  
   cell.detailTextLabel.text = [NSString stringWithFormat:@"%.0fm", [venueObject.location.distance floatValue]];  
   return cell;  
 }  
 - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath  
 {  
   // Return NO if you do not want the specified item to be editable.  
   return YES;  
 }  
 - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath  
 {  
   if (editingStyle == UITableViewCellEditingStyleDelete) {  
     [_objects removeObjectAtIndex:indexPath.row];  
     [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];  
   } else if (editingStyle == UITableViewCellEditingStyleInsert) {  
     // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.  
   }  
 }  
 /*  
 // Override to support rearranging the table view.  
 - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath  
 {  
 }  
 */  
 /*  
 // Override to support conditional rearranging of the table view.  
 - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath  
 {  
   // Return NO if you do not want the item to be re-orderable.  
   return YES;  
 }  
 */  
 @end  

2 comments:

  1. You are my hero, ultima60173!

    I just started working with RestKit and the Ray Wenderlich tutorial today, and I quickly found out that it didn't work for RestKit 0.20. Then I found this page, and was able to get the tutorial to work. RestKit is VERY cool!

    Thanks for doing the research, and posting it for others (like me) to benefit!

    =)

    ReplyDelete