web-dev-qa-db-ja.com

AFNetworkingでステータスコードを取得する方法

ユーザーを認証する方法があります。基本認証が必要です。

    NSString *url = [NSString stringWithFormat:@"%@/rest/api/person/auth", Host];
    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
    [manager setRequestSerializer:[AFHTTPRequestSerializer serializer]];
    [manager.requestSerializer setAuthorizationHeaderFieldWithUsername:_loginField.text password:_passwordField.text];
    [manager setResponseSerializer:[AFJSONResponseSerializer serializer]];
    [manager GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
        [self parseResponseForUser:responseObject];
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"Error %@ ",error);
    }];

ここでの主な問題は、エラータイプの判別です。認証のエラーとネットワーク接続の問題(ホストに到達できない)のエラーが発生する場合があります。ログインとパスワードが基準に一致しない場合、失敗ブロックが実行されます。たとえば、間違ったパスワードを入力してログインすると、次のエラーメッセージが表示されます。

エラードメイン= NSCocoaErrorDomainコード= 3840「操作を完了できませんでした。(Cocoaエラー3840。)」(JSONテキストが配列またはオブジェクトで開始されておらず、フラグメントの設定を許可するオプションがない

エラータイプをどのようにキャッチする必要がありますか?

15
abekenza

最後に見つかった答えは、誰かのために役立つかもしれません。私は使用する必要がありました:

NSInteger statusCode = operation.response.statusCode;

そして私はそれを次のように捕まえることができます:

    [manager GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSLog(@"response:%@", responseObject);
        [self parseResponseForUser:responseObject];
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSInteger statusCode = operation.response.statusCode;
        if(statusCode == 401) {
        } else if (statusCode == 404) {
        }
    }];
30
abekenza

AFNetworking 3.0以降では、エラーが発生した場合、失敗ブロックのerror.userInfoオブジェクトのステータスコードにアクセスできます。

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

    NSHTTPURLResponse *response = error.userInfo[AFNetworkingOperationFailingURLResponseErrorKey];

    NSInteger statusCode = response.statusCode;

    // Do something with the status code
}];
20
webstersx

エラーからコードを取得して、それに応じてメッセージを表示することができます。

failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSInteger statusCode = error.code;
    if(statusCode == -1001) {
      // request timed out
    } else if (statusCode == -1009 || statusCode || -1004) {
      // no internet connectivity
    }
}];

同様に、他のコードを確認できます。

6
alok srivastava

これが私のやり方です。

[self.httpClient GET:@"someAPI"
          parameters:parametersDictionary
             success:^(NSURLSessionDataTask *task, id responseObject) {
             } failure:^(NSURLSessionDataTask *task, NSError *error) {
               NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response;
               NSInteger statusCode = [response statusCode];
               switch (statusCode) {
                 case 404:
                   break;
                 default:
                   break;
               }
             }];
6
JohnVanDijk

これはSwiftでそれを行う方法です

((NSURLSessionDataTask, NSError) -> Void) = { (sessionDataTask :NSURLSessionDataTask, responseError : NSError) -> Void in
    let response  = sessionDataTask.response as! NSHTTPURLResponse
    switch (statusCode) {
      case 404:
        // do stuff
      case 401:
        // do stuff
      default:
        break;
    }
}
1
Penkey Suresh

NSURLError列挙型を使用することによるalok srivastavaの応答の改善:

failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSInteger statusCode = error.code;
if(statusCode == NSURLErrorTimedOut) {
  // request timed out
} else if (statusCode == NSURLErrorNotConnectedToInternet || statusCode || NSURLErrorCannotConnectToHost) {
  // no internet connectivity
}}];
1
solven

サーバーがHTMLで応答するか、JSONで応答する可能性があります。しかし、あなたがタイプすると:

[manager setResponseSerializer:[AFJSONResponseSerializer serializer]];

あなたはAFNetworkingにJSONを期待するように言っています。

代わりに、JSONでない場合は通常のHTTP応答を処理するように指示してください。

NSArray *serializers = @[[AFJSONResponseSerializer serializer], [AFHTTPResponseSerializer serializer]];
AFCompoundSerializer *compoundResponseSerializer = [AFCompoundSerializer compoundSerializerWithResponseSerializers:serializers];
[manager setResponseSerializer:compoundResponseSerializer];

これで、JSONシリアライザーが失敗した場合、リクエストはAFHTTPResponseSerializerに渡され、JSON解析エラーの代わりに適切なHTTPエラーコードで失敗ブロックが呼び出されます。

ちなみに、AFHTTPResponseSerializerはサブクラス化が可能なため、より具体的な動作が必要な場合は、このオプションを自由に見てください。

0
Aaron Brager

サーバーがエラーを送信している場合、要求されたものとは異なるコンテンツタイプで応答を送信することがよくあります。

たとえば、Content-TypeとしてJSONを使用してリクエストを送信し、サーバーからのJSONレスポンスを期待する場合、次のリクエストヘッダーを指定します。

_Content-Type: application/json
Accept: application/json
_

認証エラーのためにリクエストが失敗した場合、サーバーは401 (Unauthorized)のステータスコードに加えて、関連する診断情報を含むオプションのレスポンスを送信する場合があります。

厳密に言えば、WebサーバーはAcceptヘッダーを尊重する必要がありますが、残念ながら、そうでないものもあり、たとえば、「標準」エラー応答を_text/html_で送信します。ただし、詳細はAPIで指定する必要があります。

実装では、このケースを適切に処理する必要があります。つまり、応答ハンドラは、応答の_Content-Type_、つまり_text/html_に従って応答データをエンコード(または解析)するか、適切な場合は無視する必要があります。より正確には、常にHTTPステータスコードとコンテンツタイプをクエリし、情報に基づいて応答の処理方法を決定する必要があります。

AFNでその問題を解決する方法については、Aron Bragerの回答を参照してください。

0
CouchDeveloper