Лучшая практика AFNetworking для отделения логики от контроллеров представления и ответственности за отображение данных

Я использую AFNetworking как хорошая библиотека для работы с сетью. Обычно у меня есть некоторые API класс, который обрабатывает все запросы к серверу. API Этот класс является одноэлементным и включает в себя некоторую базовую конфигурацию URL, несколько блоков (замыканий), успешное завершение и невозможность передачи данных обратно на запрошенный контроллер (объект) и обновления пользовательского интерфейса / представления нового контроллера представления и т. д.

Мой вопрос, это нормально, чтобы обработать ошибку оповещения непосредственно в классе API. Например, если мы получили какой-либо сервер форм ошибок, нужно ли мне обрабатывать эти ошибки непосредственно в классе API или передавать их обратно контроллеру, и контроллер на основе обратного вызова с типом ошибки покажет необходимое предупреждение с жестко закодированной информацией. Например, "Вы ввели неверный адрес электронной почты или пароль" и т. Д.

Также это лучший метод обработки ошибок от бэкэнда в блоке успеха или в блоке сбоя AFNetworking например, когда мы GET/POST/PUT/DELET что-то.

Как я знаю, у нас много ошибок кода http, которые мы можем обрабатывать автоматически (код ошибки 400, неправильный запрос и т. Д.). Но что, если это пользовательская ошибка, какой код состояния лучше для этой ситуации, и я думаю, что ответ - мы должны использовать failure обратный вызов для обработки ошибки с сервера. Но что уточнить, если это пользовательская ошибка.

Суммировать

  1. Первый вопрос касается реализации показа пользователю предупреждений на основе ошибок. Какой класс мы должны использовать для этого (или это зависит).
  2. Второй вопрос о блоке успеха / неудачи, который должен обрабатывать пользовательскую ошибку, или нам нужно switch ошибка каждый раз при сбое блока AFNeteworking

2 ответа

Подведем итоги 1. В классе API (подкласс AFHTTPSessionManager), который обрабатывает все запросы к серверу, добавьте приведенный ниже код методов. API Call ---

- (void)getMyRecordsFromServer:(NSString *)url withLastModified:(NSTimeInterval)lastModified callbackHandler:(void (^)(id, NSError *))handler {

  self.requestSerializer = [AFHTTPRequestSerializer serializer];
  self.responseSerializer = [AFHTTPResponseSerializer serializer];


  [self GET:url parameters:nil success:^(NSURLSessionDataTask *task, id responseObject) {
    handler(responseObject, nil);

} failure:^(NSURLSessionDataTask *task, NSError *error) {

    /**********************************************************************/
    NSHTTPURLResponse *response = error.userInfo[AFNetworkingOperationFailingURLResponseErrorKey];
    NSInteger statusCode = response.statusCode;
    NSLog(@"Error Code=%ld",(long)statusCode);
    NSLog(@"Desc=%@",response.description);
    /**********************************************************************/
    [self baseFailureWithError:error onFailure:handler];

}];

}

Успешный звонок ----

 - (void)myGetRequestWithSuccess:(void (^)(id))success
              onFailure:(void (^)(NSError *))failure
 {
     [self GET:@"api/object"
           parameters:nil
           success:^(NSURLSessionDataTask *task, id responseObject)
           {
                 // success code here.
           } failure:^(NSURLSessionDataTask *task, NSError *error)
           {
            [[self class] baseFailureWithError:error onFailure:failure];
           }];
 }

после этого реализуйте универсальную логику в методе baseFailureWithError:: class и затем перезвоните вашему контроллеру представления, чтобы реализовать специфическую для пользователя проверку ошибок. Отказ вызова ----

 - (void)baseFailureWithError:(NSError *)error
               onFailure:(void(^)(id responseObject,NSError *error))failure
 {
if (failure){
    NSHTTPURLResponse *response = error.userInfo[@"AFNetworkingOperationFailingURLResponseErrorKey"];

    if ([response isKindOfClass:[NSHTTPURLResponse class]] && response.statusCode == 401){
        NSLog(@"Handle all 401's!");
        // decide show alert or not for point 2
    } else {
        failure(nil, error);
    }
  }
}

Первый вопрос касается реализации показа пользователю предупреждений на основе ошибок. Какой класс мы должны использовать для этого (или это зависит).

В этом пункте довольно много вариантов, стоит подумать. Но я поделюсь своим опытом. Для решения подобных задач я использую собственный класс для отображения предупреждений в приложении. Это сделано из-за высокой настройки оповещения в одном классе.

Пример:

CustomAlertController.alert("Test title", message: "message", acceptMessage: "OK") { () -> () in

}

Основываясь на шаблонах, которые вы используете, вы можете определить, где вы должны показывать предупреждение. В моем приложении я использую MVC. Поэтому мой класс ViewController должен показывать диалоговое окно с предупреждением, основанное на правилах MVC.

пример

 MainViewController -> (Ask for data) NetworkController -> (Response with completion block) -> MainViewController -> (Show alert with response)

Второй вопрос о блоке успеха / сбоя, который должен обрабатывать пользовательскую ошибку, или мы должны каждый раз переключать ошибку в блоке сбоя AFNeteworking

Мне нравится исследовать новые фреймворки (Moya), представленные на Github, поэтому я нашел такую, которая дает мне представление о простой в использовании и управлении фреймворком, который дает возможность обрабатывать сетевые запросы. Поэтому, основываясь на них, можно ответить на ваш вопрос.

Небольшой пример из моей:

provider.request(.Zen) { result in
    switch result {
    case let .Success(moyaResponse):
        // do something with the response data or statusCode
    case .Failure(error):
        // this means there was a network failure - either the request
        // wasn't sent (connectivity), or no response was received (server
        // timed out).  If the server responds with a 4xx or 5xx error, that
        // will be sent as a ".Success"-ful response.
    }
}

Поскольку можно сделать вывод об использовании регистра переключателя для обработки результата запроса, это очень хороший подход из-за высокой читаемости кода и простоты.

Другие вопросы по тегам