Лучшая практика AFNetworking для отделения логики от контроллеров представления и ответственности за отображение данных
Я использую AFNetworking
как хорошая библиотека для работы с сетью. Обычно у меня есть некоторые API
класс, который обрабатывает все запросы к серверу. API
Этот класс является одноэлементным и включает в себя некоторую базовую конфигурацию URL, несколько блоков (замыканий), успешное завершение и невозможность передачи данных обратно на запрошенный контроллер (объект) и обновления пользовательского интерфейса / представления нового контроллера представления и т. д.
Мой вопрос, это нормально, чтобы обработать ошибку оповещения непосредственно в классе API. Например, если мы получили какой-либо сервер форм ошибок, нужно ли мне обрабатывать эти ошибки непосредственно в классе API или передавать их обратно контроллеру, и контроллер на основе обратного вызова с типом ошибки покажет необходимое предупреждение с жестко закодированной информацией. Например, "Вы ввели неверный адрес электронной почты или пароль" и т. Д.
Также это лучший метод обработки ошибок от бэкэнда в блоке успеха или в блоке сбоя AFNetworking
например, когда мы GET/POST/PUT/DELET
что-то.
Как я знаю, у нас много ошибок кода http, которые мы можем обрабатывать автоматически (код ошибки 400, неправильный запрос и т. Д.). Но что, если это пользовательская ошибка, какой код состояния лучше для этой ситуации, и я думаю, что ответ - мы должны использовать failure
обратный вызов для обработки ошибки с сервера. Но что уточнить, если это пользовательская ошибка.
Суммировать
- Первый вопрос касается реализации показа пользователю предупреждений на основе ошибок. Какой класс мы должны использовать для этого (или это зависит).
- Второй вопрос о блоке успеха / неудачи, который должен обрабатывать пользовательскую ошибку, или нам нужно
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.
}
}
Поскольку можно сделать вывод об использовании регистра переключателя для обработки результата запроса, это очень хороший подход из-за высокой читаемости кода и простоты.