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");
}];
}
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.