AFNetworking 2.0 AFHTTPSessionManager: how to get status code and response JSON in failure block?

后端 未结 7 787
你的背包
你的背包 2020-12-04 10:08

When switched to AFNetworking 2.0 the AFHTTPClient has been replaced by AFHTTPRequestOperationManager / AFHTTPSessionManager (as mentioned in the migration guide). The very

相关标签:
7条回答
  • 2020-12-04 10:37

    After of read and research for several days, It worked for me:

    1) You have to build your own subclass of AFJSONResponseSerializer

    File : JSONResponseSerializerWithData.h:

    #import "AFURLResponseSerialization.h"
    
    /// NSError userInfo key that will contain response data
    static NSString * const JSONResponseSerializerWithDataKey = @"JSONResponseSerializerWithDataKey";
    
    @interface JSONResponseSerializerWithData : AFJSONResponseSerializer
    @end
    

    File: JSONResponseSerializerWithData.m

    #import "JSONResponseSerializerWithData.h"
    
    @implementation JSONResponseSerializerWithData
    
    - (id)responseObjectForResponse:(NSURLResponse *)response
                               data:(NSData *)data
                              error:(NSError *__autoreleasing *)error
    {
        id JSONObject = [super responseObjectForResponse:response data:data error:error];
        if (*error != nil) {
            NSMutableDictionary *userInfo = [(*error).userInfo mutableCopy];
            if (data == nil) {
    //          // NOTE: You might want to convert data to a string here too, up to you.
    //          userInfo[JSONResponseSerializerWithDataKey] = @"";
                userInfo[JSONResponseSerializerWithDataKey] = [NSData data];
            } else {
    //          // NOTE: You might want to convert data to a string here too, up to you.
    //          userInfo[JSONResponseSerializerWithDataKey] = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
                userInfo[JSONResponseSerializerWithDataKey] = data;
            }
            NSError *newError = [NSError errorWithDomain:(*error).domain code:(*error).code userInfo:userInfo];
            (*error) = newError;
        }
    
        return (JSONObject);
    }
    

    2) Setup your own JSONResponseSerializer in your AFHTTPSessionManager

    + (instancetype)sharedManager
    {
        static CustomSharedManager *manager = nil;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            manager = [[CustomSharedManager alloc] initWithBaseURL:<# your base URL #>];
    
            // *** Use our custom response serializer ***
            manager.responseSerializer = [JSONResponseSerializerWithData serializer];
        });
    
        return (manager);
    }
    

    Source: http://blog.gregfiumara.com/archives/239

    0 讨论(0)
  • 2020-12-04 10:39

    You can access the “data” object directly from AFNetworking by using the “AFNetworkingOperationFailingURLResponseDataErrorKey” key so there is no need for subclassing the AFJSONResponseSerializer. You can the serialize the data into a readable dictionary. Here is some sample code to get JSON Data :

     NSData *errorData = error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey];
     NSDictionary *serializedData = [NSJSONSerialization JSONObjectWithData: errorData options:kNilOptions error:nil];
    

    Here is the code to Get Status code in the Failure block:

      NSHTTPURLResponse* r = (NSHTTPURLResponse*)task.response;
      NSLog( @"success: %d", r.statusCode ); 
    
    0 讨论(0)
  • 2020-12-04 10:43

    You can get the userInfo dictionary associated with the NSError object and traverse down that to get the exact response you need. For example in my case I get an error from a server and I can see the userInfo like in ScreeShot

    ScreenShot displaying AFNetworking error

    0 讨论(0)
  • 2020-12-04 10:45

    You can get the status code like this, read the failure block...

     NSURLSessionDataTask *op = [[IAClient sharedClient] POST:path parameters:paramsDict constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
        } success:^(NSURLSessionDataTask *task, id responseObject) {
            DLog(@"\n============= Entity Saved Success ===\n%@",responseObject);
    
            completionBlock(responseObject, nil);
        } failure:^(NSURLSessionDataTask *task, NSError *error) {
            DLog(@"\n============== ERROR ====\n%@",error.userInfo);
            NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response;
            int statuscode = response.statusCode;}
    
    0 讨论(0)
  • 2020-12-04 10:46

    In Swift 2.0 (in case you cannot use Alamofire yet):

    Get status code:

    if let response = error.userInfo[AFNetworkingOperationFailingURLResponseErrorKey] as? NSHTTPURLResponse {
        print(response.statusCode)
    }
    

    Get response data:

    if let data = error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] as? NSData {
        print("\(data.length)")
    }
    

    Some JSON REST APIs return error messages in their error responses (Amazon AWS services for example). I use this function to extract the error message from an NSError that has been thrown by AFNetworking:

    // Example: Returns string "error123" for JSON { message: "error123" }
    func responseMessageFromError(error: NSError) -> String? {
        do {
            guard let data = error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] as? NSData else {
                return nil
            }
            guard let json = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments) as? [String: String] else {
                return nil
            }
            if let message = json["message"] {
                return message
            }
            return nil
        } catch {
            return nil
        }
    }
    
    0 讨论(0)
  • 2020-12-04 10:47

    You can access the “data” object directly from AFNetworking by using the “AFNetworkingOperationFailingURLResponseDataErrorKey” key so there is no need for subclassing the AFJSONResponseSerializer. You can the serialize the data into a readable dictionary. Here is some sample code :

     NSData *errorData = error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey];
     NSDictionary *serializedData = [NSJSONSerialization JSONObjectWithData: errorData options:kNilOptions error:nil];
    
    0 讨论(0)
提交回复
热议问题