AFNetworking выдает ошибку, но как ее отобразить?
У меня есть приложение, где пользователь может пройти аутентификацию с Instapaper. Однако для этого им нужна подписка Instapaper, поэтому, если они попытаются войти в систему с учетной записью, которая не подписана на Instapaper, я хочу показать им ошибку.
Но когда они пытаются войти, AFNetworking видит это как успешное, а затем отображает эту ошибку на консоли:
Ошибка: Ошибка Домен =AFNetworkingErrorDomain Code=-1011 "Ожидаемый код состояния в (200-299), получено 400" UserInfo=0x8374840 {NSLocalizedRecoverySuggestion=[{"error_code": 1041, "message": "Требуется учетная запись подписки", тип " ":" error "}], AFNetworkingOperationFailingURLRequestErrorKey = https: //www.instapaper.com/api/1/bookmarks/list>, NSErrorFailingURLKey = https://www.instapaper.com/api/1/bookmarks/list, NSLocalizedDescription = Ожидаемый код состояния в (200-299), получил 400, AFNetworkingOperationFailingURLResponseErrorKey=}
Я использую только AFXAuthClient, который является модификацией AFNetworking. Я вложил его в подкласс, чтобы создать собственный клиент Instapaper API, который выглядит следующим образом:
#import "AFInstapaperClient.h"
#import "AFJSONRequestOperation.h"
@implementation AFInstapaperClient
+ (AFInstapaperClient *)sharedClient {
static AFInstapaperClient *sharedClient = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedClient = [[AFInstapaperClient alloc] initWithBaseURL:[NSURL URLWithString:@"https://www.instapaper.com/"]
key:@"..."
secret:@"..."];
});
return sharedClient;
}
- (id)initWithBaseURL:(NSURL *)url {
if (self = [super initWithBaseURL:url]) {
[self registerHTTPOperationClass:[AFJSONRequestOperation class]];
[self setDefaultHeader:@"Accept" value:@"application/json"];
}
return self;
}
@end
И когда они входят в систему, выполняется следующий код:
- (IBAction)doneButtonPressed:(UIBarButtonItem *)sender {
[[AFInstapaperClient sharedClient] authorizeUsingXAuthWithAccessTokenPath:@"/api/1/oauth/access_token"
accessMethod:@"POST"
username:self.loginBox.text
password:self.passwordBox.text
success:^(AFXAuthToken *accessToken) {
// Save the token information into the Keychain
[UICKeyChainStore setString:accessToken.key forKey:@"InstapaperKey"];
[UICKeyChainStore setString:accessToken.secret forKey:@"InstapaperSecret"];
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:@"Login Successful"
message:@"Your articles are being downloaded now and will appear in your queue."
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles: nil];
[alert show];
[[NSUserDefaults standardUserDefaults] setObject:@"YES" forKey:@"IsLoggedInToInstapaper"];
[self dismissViewControllerAnimated:YES completion:nil];
}
failure:^(NSError *error) {
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:@"Login Failed."
message:@"Are you connected to the internet? Instapaper may also be down. Try again later."
delegate:nil
cancelButtonTitle:@"Okay"
otherButtonTitles: nil];
[alert show];
}];
}
Но код никогда не входит в блок сбоя. Как я могу изменить свой код, чтобы он мог сказать им, что им нужен подписной аккаунт Instapaper?
2 ответа
Исходя из вашей ситуации, я не думаю, что вы когда-нибудь вызовете блокировку сбоя, потому что ваш запрос не сбой. Вы получаете ответ от веб-службы. По моему опыту блок сбоя выполняется только в том случае, если вы не получили ответ из-за чего-то вроде доступности сети или чего-то подобного.
Поэтому вам нужно обработать ошибку учетной записи в блоке успеха. Один из способов сделать это - прочитать код состояния, который возвращается в ответе. Если код состояния 400, как показывает ваша консоль, предупредите пользователя.
Вы можете следовать методу, используемому здесь /questions/43434589/est-li-prostoj-sposob-poluchit-kod-sostoyaniya-http-v-bloke-sboya-ot-afhttpclient
Кажется, что с этой реализацией, как сказал WeekendCodeWarrior, она будет считаться успешной, даже если они не смогут делать дальнейшие запросы. Код, который выплевывал ошибку, на самом деле был NSLog, который я сделал (упс, не понял, что это был мой код, выводящий это) после выполнения запроса, поскольку я предполагал, что все в порядке.
Мое решение состояло в том, чтобы просто сделать запрос к API в этом блоке успеха, проверить результат этого запроса (который имеет response
объект вернулся), а затем действовать соответственно на response
объект.