I have used many hours on how to solve this issue. Im using Restkit 0.9.3 with Object Mapping 2.0. All data is in JSON. I can make GET, POST, PUT and DELETE operations corre
For version 0.10.0 this response error can be mapped as follows:
RKObjectMapping *errorMapping = [RKObjectMapping mappingForClass:[RKErrorMessage class]];
[errorMapping mapKeyPath:@"message" toAttribute:@"errorMessage"];
[[[RKObjectManager sharedManager] mappingProvider] setErrorMapping:errorMapping];
Requests that return an error will call the following delegate method:
- (void)objectLoader:(RKObjectLoader *)objectLoader didFailWithError:(NSError *)error {
NSArray *errorMessages = [[error userInfo] objectForKey:RKObjectMapperErrorObjectsKey];
RKErrorMessage *errorMessage = [errorMessages objectAtIndex:0]; // First and only object in your case.
NSString *message = [errorMessage errorMessage];
NSInteger code = [[objectLoader response] statusCode];
NSLog(@"ERROR: [%d] %@", code, message); // => ERROR: [401] Unauthorized
}
if an object is returned your delegate should call this method:
- (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects {}
in this method you should call an instance of your "error" class and map 'code' and 'message' as necessary.
An easier way to handle errors though would be to use:
- (void)objectLoader:(RKObjectLoader*)objectLoader didFailWithError:(NSError*)error {
if(objectLoader.response.statusCode == 401)
{ ...
And show the necessary error message in that method.
For RestKit v0.20
assuming your HTTP body is:
{"error": "..."}
you create an the mapping and descriptor:
RKObjectMapping *errorMapping = [RKObjectMapping mappingForClass:[RKErrorMessage class]];
[errorMapping addPropertyMapping: [RKAttributeMapping attributeMappingFromKeyPath:@"error" toKeyPath:@"errorMessage"]];
RKResponseDescriptor *errorResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:errorMapping pathPattern:nil keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassClientError)];
[objectManager addResponseDescriptor:errorResponseDescriptor];
and then you can access it from your failure block:
failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(@"errorMessage: %@", [[error userInfo] objectForKey:RKObjectMapperErrorObjectsKey]);
}
This uses the built-in RKErrorMessage
class, though you can create your own custom class with additional fields.
Using Restkit v0.2x you can map all JSON attributes you want to the already existing RKErrorMessage.userInfo
Dictionary property in this [Swift] way:
let errorMapping = RKObjectMapping(forClass: RKErrorMessage.self);
errorMapping.addPropertyMapping(RKAttributeMapping(fromKeyPath: nil, toKeyPath: "userInfo"));
let errorResponseDescriptor = RKResponseDescriptor(
mapping: errorMapping,
method: RKRequestMethod.Any,
pathPattern: nil,
keyPath: "error", //or nil, according to your json response
statusCodes: RKStatusCodeIndexSetForClass(UInt(RKStatusCodeClassClientError)))
);
So, you can map an error JSON response like this one:
{
"error": {
"message": "Error message",
"cause": "...",
"code": "my_error_code",
"url": "..."
...
}
}
And retrieve the RKErrorMessage
with all attributes, in a failure
closure, as follows:
failure: { (operation, error) -> Void in
if let errorMessage = error.userInfo?[RKObjectMapperErrorObjectsKey]?.firstObject as? RKErrorMessage{
let message = errorMessage.userInfo["message"] as! String;
let code = errorMessage.userInfo["code"] as! String;
...
}
}
I hope this can be helpful to someone!