Search code examples
iosrestkit

iOS RestKit custom error handling


I'm trying to find a best way of processing results from API. I went through number of tutorials and guides, but none of them were able to provide me guidance how to correctly process custom errors from API.

The best tutorial I found I followed is this one, but I'm still missing the final piece - error processing:

http://www.nsscreencast.com/episodes/51-intro-to-restkit-mapping

Every API function (GET, POST, PUT and DELETE) in our project returns following JSON output:

{result: TRUE/FALSE, data:(string, object or array), error_message:"custom error message"}

If result is TRUE, data is returned, otherwise error_message is returned. Every request returns code 200 or 404 as a result, but 404 is only returned if API URL was not found. Here is an example of getting cities in specific country. If I try to get cities from a country which is not in the database, API returns FALSE and custom error message.

The question is, how can I handle this situation?

LocalityCity.h

@interface LocalityCity : NSObject

@property (nonatomic) int idCity;
@property (nonatomic, strong) NSString *name;

@end

RestMappingProvider.m

+ (RKObjectMapping *)localityCityMapping
{
    RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[LocalityCity class]];

    [mapping addAttributeMappingsFromDictionary:@{
                                                  @"id": @"idCity",
                                                  @"name": @"name",
                                                  }];

    return mapping;
}

RestDescriptorProvider.m

+ (void)localityCityDescriptor
{
    RKResponseDescriptor *responseDescriptorGet =
    [RKResponseDescriptor responseDescriptorWithMapping:[RestMappingProvider localityCityMapping]
                                                 method:RKRequestMethodGET
                                            pathPattern:@"/api/locality/cities/:id"
                                                keyPath:nil
                                            statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];

    [[RKObjectManager sharedManager] addResponseDescriptor:responseDescriptorGet];
}

LocalityCityViewController.m

@interface CityViewController ()

@property (nonatomic, strong) NSArray *cities;

@end

@implementation CityViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    [[RestDescriptorProvider localityCityDescriptor];
    [[RKObjectManager sharedManager] getObject:self.cities
                                          path:@"/api/locality/cities/2"
                                    parameters:nil
                                       success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
                                           NSLog(@"OK");
                                       } failure:^(RKObjectRequestOperation *operation, NSError *error) {
                                           NSLog(@"Error");
                                       }];
}

Solution

  • Ideally the web service would use one of the HTTP status codes to tell the client there was a problem, then you could use a response descriptor specifically to handle that and an NSError.

    You can use a dynamic mping which checks the result type and determines how to process the result. Depending on the flag value a different mapping will be applied to create a different result class with the appropriate details for you to use. Exactly how you handle that is up to you, either with a class type check, or perhaps having your model objects return a 'success' flag, perhaps supported by a protocol.