3

I am trying to map a 403 forbidden respone to a custom object. I registered a mapping with the response code as follows:

RKResponseDescriptor* tacResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:termsAndConditionMapping pathPattern:@"user" keyPath:nil statusCodes:[NSIndexSet indexSetWithIndex:403]];
[objectManager addResponseDescriptor:tacResponseDescriptor];

But when the 403 response is send from the server, I just get a 'Non-successful status code encountered: performing mapping with nil target object' log from RestKit and the failure block is executed with the operation's mappingResult property being nil. What am I doing wrong here? I need to map one specific error case of a specific path to a specific object.

Best regards, Michael

Michael Ochs
  • 2,846
  • 3
  • 27
  • 33

2 Answers2

1

I'm not entirely sure what you mean, but there's no mappingResult property if you end up in the failure block. But the error can be found hidden in the operation property:

[[[operation.error userInfo] objectForKey: RKObjectMapperErrorObjectsKey] firstObject];
Kevin R
  • 8,230
  • 4
  • 41
  • 46
0

When the response status code is not 2xx the failure block will be called, you can catch your custom error there, switching on operation.HTTPRequestOperation.response.statusCode

If you want to handle errors with RestKit, in a more generic way, you can consider to add to your RKObjectManager a response descriptor for all 4xx and 5xx errors - in this example i'll map error with this body structure

{"errorCode":"996","errorMessage":"This is my custom error message"}

Configure your RKObjectManager:

RKObjectMapping* errorMapping = [RKObjectMapping mappingForClass:[RKErrorMessage class]];
[errorMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"errorMessage" toKeyPath:@"errorMessage"]];
[errorMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:nil toKeyPath:@"userInfo"]];
NSIndexSet *clientErrorStatusCode = RKStatusCodeIndexSetForClass(RKStatusCodeClassClientError); // Any response in the 4xx
NSIndexSet *serverErrorStatusCode = RKStatusCodeIndexSetForClass(RKStatusCodeClassServerError); // Any response in the 5xx
RKResponseDescriptor *clientErrorDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:errorMapping method:RKRequestMethodAny pathPattern:nil keyPath:@"" statusCodes:clientErrorStatusCode];
RKResponseDescriptor *serverErrorDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:errorMapping method:RKRequestMethodAny pathPattern:nil keyPath:@"" statusCodes:serverErrorStatusCode];
//... Remember to add response descriptors to your object manager

And then in the failure block of your requests you can switch on the status code and handle the error:

failure:^(RKObjectRequestOperation *operation, NSError *error) {
    RKErrorMessage *errorMessage = [[error.userInfo objectForKey:RKObjectMapperErrorObjectsKey] firstObject];
    NSString *errorCode = [errorMessage.userInfo objectForKey:@"errorCode"];

    if (operation.HTTPRequestOperation.response.statusCode == 304){
         //Handle your 304 error
    }
}
andreacipriani
  • 2,519
  • 26
  • 23