2013-12-13 11 views
14

Mam metodę autoryzacji użytkownika. Potrzebuję podstawowej autoryzacji.Jak uzyskać kod statusu w 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); 
    }]; 

Głównym problemem jest tutaj określenie typu błędu. Być może wystąpił błąd autoryzacji i błędu w przypadku problemu z połączeniem sieciowym (host nie jest osiągalny). Gdy login i hasło nie są zgodne z kryteriami, blokada działa. Na przykład, jeśli kładę złe hasło i zalogować biorę ten komunikat o błędzie .:

Error Code NSCocoaErrorDomain Domain = 3840 = "Operacja nie mogła być zakończone. (Cocoa błąd 3840.)" (tekst JSON nie zaczynał się od tablicy lub obiektu i opcji zezwalającej na brak fragmentów.)

Jak mogę przechwytywać typy błędów?

+0

Czy możesz umieścić JSON, który próbujesz dostać, proszę? –

+0

Zaktualizowałem moje pytanie, napisałem odpowiedź, że próbuję uzyskać – abekenza

Odpowiedz

30

Wreszcie znaleziona odpowiedź, może być pomocna dla kogoś. Potrzebne mi było używać:

NSInteger statusCode = operation.response.statusCode; 

i mogę złapać to lubią:

[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) { 
     } 
    }]; 
+1

NSInteger powinien być używany w miarę przechodzenia do 64-bitowego łuku. – ryanconnellyatl

+4

To nie jest poprawne dla 'AFURLSessionManager', który używa zadań, a nie' AFHTTPRequestOperation' –

-1

Twój Json musi być:

{ 
    "access" : "1", 
    "admin" : "0", 
    "code" : "constantine2", 

    ... 

    "positions" : [ 
       { 
      "departmentID" : "992c93ee-2fa7-4e53-be5f-4e32a45ba5e6", 
      "departmentName" : "Dev-C++ resources page (libraries, sources, updates...)", 
      .... 
     } 
    ], 
    "userid" : "3b660c13-b856-41fa-a386-814a7b43bacc" 
} 
+0

Jestem pewien, że JSON ma rację, ponieważ mogę parsować dane, kiedy wpisuję prawidłowy login i hasło. Problem pojawia się, gdy wpisuję nieprawidłowy login lub hasło. Strona serwera wysyła mi odpowiedź html (błąd 401, użytkownik nie jest autoryzowany) zamiast json. Chciałabym przechwycić błędy, więc jeśli typ błędu jest równy 401, chcę pokazać widok alertu typu "Użytkownik nie jest autoryzowany", jeśli typ błędu jest równy 404, chcę pokazać użytkownikowi "niepoprawny komunikat URL". Każda pomoc będzie doceniona. – abekenza

+0

Zamiast wpisywać -1 napisz poprawnie swoje pytanie. Odpowiedź brzmi: pierwszy z [self parseResponseForUser: responseObject]; sprawdź treść i typ obiektu responceObject oraz czy (jest 404?) {alert} else {[self parseResponseForUser: responseObject];} – Dimentar

+0

Nie wstawiłem -1. Mam tylko 13 reputacji, nie mogę nawet głosować. Mogę tylko wybrać najlepszą odpowiedź teraz – abekenza

0

Wygląda na to serwer może reagować z HTML, lub może odpowiedzieć JSON. Ale gdy wpiszesz:

[manager setResponseSerializer:[AFJSONResponseSerializer serializer]]; 

Mówisz AFNetworking, aby oczekiwać JSON.

Zamiast próbować mówienie go obsługiwać regularne odpowiedź HTTP, jeśli nie jest to JSON:

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

Teraz, gdy serializer JSON zawiedzie, wniosek zostanie przekazany do AFHTTPResponseSerializer, co powinno wywołać swój blok awarii z odpowiednim kodem błędu HTTP zamiast z błędem parsowania JSON.

Nawiasem mówiąc, AFHTTPResponseSerializer ma podklasę, więc zachęcamy do zapoznania się z tą opcją, jeśli chcesz bardziej specyficzne zachowanie.

+0

Dzięki, AAron. Dzisiaj próbowałem tego rozwiązania, ale utknąłem, skąd powinienem zaimportować AFCompoundSerializer. Czytanie dokumentacji AFNetworking Znalazłem metodę uzyskiwania statusu. – abekenza

0

Zdarza się często, że serwery mogą wysyłać odpowiedź o innej treści niż żądana, jeśli wysyłają błąd.

Na przykład podczas wysyłania żądania z JSON jako Content-Type i spodziewa się odpowiedzi JSON z serwera, można by określić następujące nagłówki żądanie:

Content-Type: application/json 
Accept: application/json 

Jeżeli wniosek nie powiedzie z powodu błędu uwierzytelniania serwer może przesłać kod stanu 401 (Unauthorized) oraz opcjonalną odpowiedź zawierającą odpowiednie informacje diagnostyczne.

Ściśle, serwery internetowe powinny respektować nagłówek Accept, ale niestety, niektóre nie wysyłają "standardowej" odpowiedzi na błąd na przykład w text/html. Jednak szczegóły powinny zostać określone w interfejsie API.

Twoje wdrożenie powinno załatwić sprawę z wdziękiem. Oznacza to, że program obsługi odpowiedzi musi zakodować (lub przeanalizować) dane odpowiedzi zgodnie z Content-Type odpowiedzi, na przykład text/html lub zignorować, jeśli jest to odpowiednie. Dokładniej, zawsze powinieneś zapytać o kod statusu HTTP ORAZ typ zawartości, a następnie podjąć świadomą decyzję, w jaki sposób chcesz potraktować odpowiedź.

Zobacz odpowiedź Arona Bragera, jak rozwiązać ten problem z AFN.

6

można dać spróbować uzyskać kod błędu, a następnie wyświetlić wiadomości odpowiednio.

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

Podobnie można sprawdzić na innym kodem.

5

Oto jak to zrobić.

[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; 
       } 
      }]; 
17

W AFNetworking 3.0+ oraz w przypadku wystąpienia błędu, można uzyskać dostęp do kodu stanu w error.userInfo obiektu w bloku niepowodzenia w:

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

    NSHTTPURLResponse *response = error.userInfo[AFNetworkingOperationFailingURLResponseErrorKey]; 

    NSInteger statusCode = response.statusCode; 

    // Do something with the status code 
}]; 
+0

Dzięki to działa dla mnie –

0

Lepsza reakcja ALOK Srivastava za pomocą NSURLError enum :

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

Oto jak to zrobić w 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; 
    } 
} 
Powiązane problemy