Отказ от ответа администратора

Я использовал много часов на том, как решить эту проблему. Im использует Restkit 0.9.3 с Object Mapping 2.0. Все данные находятся в JSON. Я могу корректно выполнить операции GET, POST, PUT и DELETE, это тело ответа, которое я не собираю и не картировать.

Итак, моя проблема заключается в том, что мой restil api возвращает ошибки, когда что-то идет не так. Я хочу сопоставить эти ошибки с restkit, fx эта ошибка возвращается:

{ "код": "401", "сообщение": "Неавторизованный" }

Как правильно сопоставить этот json? Я пробовал много вещей и мог использовать некоторую ориентировку - или, пожалуйста, дайте пример этого.

Ответ 1

Для версии 0.10.0 эта ошибка ответа может быть отображена следующим образом:

RKObjectMapping *errorMapping = [RKObjectMapping mappingForClass:[RKErrorMessage class]];
[errorMapping mapKeyPath:@"message" toAttribute:@"errorMessage"];
[[[RKObjectManager sharedManager] mappingProvider] setErrorMapping:errorMapping];

Запросы, возвращающие ошибку, вызовут следующий метод делегирования:

- (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
}

Ответ 2

Для RestKit v0.20

Предполагая, что ваше тело HTTP:

{"error": "..."}

вы создаете отображение и дескриптор:

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];

а затем вы можете получить к нему доступ из блока отказов:

failure:^(RKObjectRequestOperation *operation, NSError *error) {
                NSLog(@"errorMessage: %@", [[error userInfo] objectForKey:RKObjectMapperErrorObjectsKey]);
            }

Это использует встроенный класс RKErrorMessage, хотя вы можете создать свой собственный пользовательский класс с дополнительными полями.

Ответ 3

Используя Restkit v0.2x, вы можете сопоставить все атрибуты JSON, которые вы хотите, с уже существующим свойством RKErrorMessage.userInfo Словарь в этом [ Swift] образом:

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)))
);

Итак, вы можете сопоставить ответ JSON с ошибкой, подобный этому:

{
    "error": {
        "message": "Error message",
        "cause": "...",
        "code": "my_error_code",
        "url": "..."
        ...
    }
}

И извлеките RKErrorMessage со всеми атрибутами в закрытии failure следующим образом:

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;
        ...
    }
}

Я надеюсь, что это может быть полезно кому-то!

Ответ 4

если объект возвращается, ваш делегат должен вызвать этот метод:

- (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects {}

в этом методе вы должны вызвать экземпляр класса "ошибка" и "код" карты и "сообщение" по мере необходимости.

Более простой способ обработки ошибок, но должен был бы использовать:

- (void)objectLoader:(RKObjectLoader*)objectLoader didFailWithError:(NSError*)error {

if(objectLoader.response.statusCode == 401)
{ ...

И покажите необходимое сообщение об ошибке в этом методе.