iOS学习----------AFNetworking(4)responseSerialization

来源:互联网 发布:qq一手数据出售群 编辑:程序博客网 时间:2024/05/22 15:33

在AFN中,通过类AFURLResponseSerialization对服务器返回的数据进行格式化(json/xml…),下面对这个类中主要的方法进行解析。
AFURLResponseSerialization.h文件
协议:AFURLResponseSerialization

//主要是判断返回的response是否可用- (BOOL)validateResponse:(NSHTTPURLResponse *)response                    data:(NSData *)data                   error:(NSError * __autoreleasing *)error{    BOOL responseIsValid = YES;    NSError *validationError = nil;    // 简单的为空判断和类型判断,注意如果response为空或类型不对,反而responseValid为YES    if (response && [response isKindOfClass:[NSHTTPURLResponse class]]) {        // 如果response对应的mimeType不被这个ResponseSerializer所接受,那么就认为Response不可用//acceptableContentTypes保存了 每个类能解析的内容的类型         /*         json为:@"application/json",@"text/html", @"text/json", @"text/javascript"         */        if (self.acceptableContentTypes && ![self.acceptableContentTypes containsObject:[response MIMEType]]) {            //response不可用时候的处理            // 会返回unacceptable content-type的信息,并将错误信息记录在了mutableUserInfo中            if ([data length] > 0 && [response URL]) {                NSMutableDictionary *mutableUserInfo = [@{NSLocalizedDescriptionKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Request failed: unacceptable content-type: %@", @"AFNetworking", nil), [response MIMEType]],                                                          NSURLErrorFailingURLErrorKey:[response URL],                                                          AFNetworkingOperationFailingURLResponseErrorKey: response,} mutableCopy];                if (data) {mutableUserInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] = data;                }                // 利用mutableUserInfo构建一个NSError对象                validationError = AFErrorWithUnderlyingError([NSError errorWithDomain:AFURLResponseSerializationErrorDomain code:NSURLErrorCannotDecodeContentData userInfo:mutableUserInfo], validationError);            }            responseIsValid = NO;        }        // 判断返回的statusCode是否被允许 如果statuscode不在acceptableStatusCodes中那么response不可以处理error        //    self.acceptableStatusCodes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(200, 100)];        if (self.acceptableStatusCodes && ![self.acceptableStatusCodes containsIndex:(NSUInteger)response.statusCode] && [response URL]) {            NSMutableDictionary *mutableUserInfo = [@{                             NSLocalizedDescriptionKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Request failed: %@ (%ld)", @"AFNetworking", nil), [NSHTTPURLResponse localizedStringForStatusCode:response.statusCode], (long)response.statusCode],                                               NSURLErrorFailingURLErrorKey:[response URL],                                               AFNetworkingOperationFailingURLResponseErrorKey: response, } mutableCopy];            if (data) {mutableUserInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] = data;            }            validationError = AFErrorWithUnderlyingError([NSError errorWithDomain:AFURLResponseSerializationErrorDomain code:NSURLErrorBadServerResponse userInfo:mutableUserInfo], validationError);            responseIsValid = NO;        }    }    if (error && !responseIsValid) {        *error = validationError;    }    return responseIsValid;}

静态方法对error进行处理

static NSError * AFErrorWithUnderlyingError(NSError *error, NSError *underlyingError) {    if (!error) {        return underlyingError;    }    if (!underlyingError || error.userInfo[NSUnderlyingErrorKey]) {        return error;    }    NSMutableDictionary *mutableUserInfo = [error.userInfo mutableCopy];    mutableUserInfo[NSUnderlyingErrorKey] = underlyingError;    return [[NSError alloc] initWithDomain:error.domain code:error.code userInfo:mutableUserInfo];}

AFJSONResponseSerializer类
对父类的- (id)responseObjectForResponse:(NSURLResponse )response data:(NSData )data error:(NSError __autoreleasing )error进行重写

- (id)responseObjectForResponse:(NSURLResponse *)response                           data:(NSData *)data                          error:(NSError *__autoreleasing *)error{    // 判断当前response是否有效    if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error]) {        // 还记得validateResponse:中如果content-type不满足,那么产生的validationError就是Domain为AFURLResponseSerializationErrorDomain,code为NSURLErrorCannotDecodeContentData        if (!error || AFErrorOrUnderlyingErrorHasCodeInDomain(*error, NSURLErrorCannotDecodeContentData, AFURLResponseSerializationErrorDomain)) {            // 因为不支持这个content-type,所以不用解析了,直接返回nil            return nil;        }    }    id responseObject = nil;    NSError *serializationError = nil;    // Workaround for behavior of Rails to return a single space for `head :ok` (a workaround for a bug in Safari), which is not interpreted as valid input by NSJSONSerialization.    // See https://github.com/rails/rails/issues/1742    // 对于'head :ok',Rails返回的是一个空格 (这是Safari上的一个bug),并且这样的JSON格式不会被NSJSONSerialization解析。    // 如果是单个空格,就不解析    BOOL isSpace = [data isEqualToData:[NSData dataWithBytes:" " length:1]];    if (data.length > 0 && !isSpace) {        responseObject = [NSJSONSerialization JSONObjectWithData:data options:self.readingOptions error:&serializationError];    } else {        return nil;    }    // 如果需要移除JSON数据中对应value为空(nil或NSNull)的key,那么就使用AFJSONObjectByRemovingKeysWithNullValues函数    // AFJSONObjectByRemovingKeysWithNullValues通过递归的方法,把JSON中NSDictionary的数据(不包括NSArray)中的对应value为空的key移除    if (self.removesKeysWithNullValues && responseObject) {        responseObject = AFJSONObjectByRemovingKeysWithNullValues(responseObject, self.readingOptions);    }    if (error) {        // 如果serializationError不为空,那么最终的error其实就是serializationError        *error = AFErrorWithUnderlyingError(serializationError, *error);    }    return responseObject;}

AFXMLParserResponseSerializer类
返回一个NSXMLParser的解析器对xml数据进行解析 e

- (id)responseObjectForResponse:(NSHTTPURLResponse *)response data:(NSData *)data error:(NSError *__autoreleasing *)error{    if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error]) {        if (!error || AFErrorOrUnderlyingErrorHasCodeInDomain(*error, NSURLErrorCannotDecodeContentData, AFURLResponseSerializationErrorDomain)) {            return nil;        }    }    // 使用NSXMLParser解析NSData数据    return [[NSXMLParser alloc] initWithData:data];}

AFPropertyListResponseSerializer类

- (id)responseObjectForResponse:(NSURLResponse *)response                           data:(NSData *)data                          error:(NSError *__autoreleasing *)error{    if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error]) {        if (!error || AFErrorOrUnderlyingErrorHasCodeInDomain(*error, NSURLErrorCannotDecodeContentData, AFURLResponseSerializationErrorDomain)) {            return nil;        }    }    id responseObject;    NSError *serializationError = nil;    // 使用NSPropertyListSerialization来解析NSData数据    if (data) {        responseObject = [NSPropertyListSerialization propertyListWithData:data options:self.readOptions format:NULL error:&serializationError];    }    // 如果serializationError不为空,那么最终的error其实就是serializationError    if (error) {        *error = AFErrorWithUnderlyingError(serializationError, *error);    }    return responseObject;}

AFImageResponseSerializer类
类型:@”image/tiff”, @”image/jpeg”, @”image/gif”, @”image/png”, @”image/ico”, @”image/x-icon”, @”image/bmp”, @”image/x-bmp”, @”image/x-xbitmap”, @”image/x-win-bitmap”

- (id)responseObjectForResponse:(NSURLResponse *)response                           data:(NSData *)data                          error:(NSError *__autoreleasing *)error{    if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error]) {        if (!error || AFErrorOrUnderlyingErrorHasCodeInDomain(*error, NSURLErrorCannotDecodeContentData, AFURLResponseSerializationErrorDomain)) {            return nil;        }    }    // iOS和TV平台默认automaticallyInflatesResponseImage为YES    // 下面的NSData转图片的方法    if (self.automaticallyInflatesResponseImage) {   //automaticallyInflatesResponseImage设置为yes:在后台对图片进行处理,而不是在main线程中        return AFInflatedImageFromResponseWithDataAtScale((NSHTTPURLResponse *)response, data, self.imageScale);    } else {        return AFImageWithDataAtScale(data, self.imageScale);    }    return nil;}

获取到图片后的两种处理方式

第一种automaticallyInflatesResponseImage设置为yes:在后台对图片进行处理,而不是在main线程中static UIImage * AFInflatedImageFromResponseWithDataAtScale(NSHTTPURLResponse *response, NSData *data, CGFloat scale) {    if (!data || [data length] == 0) {        return nil;    }    CGImageRef imageRef = NULL;    CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);    if ([response.MIMEType isEqualToString:@"image/png"]) {        imageRef = CGImageCreateWithPNGDataProvider(dataProvider,  NULL, true, kCGRenderingIntentDefault);    } else if ([response.MIMEType isEqualToString:@"image/jpeg"]) {        imageRef = CGImageCreateWithJPEGDataProvider(dataProvider, NULL, true, kCGRenderingIntentDefault);        if (imageRef) {            CGColorSpaceRef imageColorSpace = CGImageGetColorSpace(imageRef);            CGColorSpaceModel imageColorSpaceModel = CGColorSpaceGetModel(imageColorSpace);            // CGImageCreateWithJPEGDataProvider does not properly handle CMKY, so fall back to AFImageWithDataAtScale            if (imageColorSpaceModel == kCGColorSpaceModelCMYK) {                CGImageRelease(imageRef);                imageRef = NULL;            }        }    }    CGDataProviderRelease(dataProvider);    UIImage *image = AFImageWithDataAtScale(data, scale);    if (!imageRef) {        if (image.images || !image) {            return image;        }        imageRef = CGImageCreateCopy([image CGImage]);        if (!imageRef) {            return nil;        }    }    size_t width = CGImageGetWidth(imageRef);    size_t height = CGImageGetHeight(imageRef);    size_t bitsPerComponent = CGImageGetBitsPerComponent(imageRef);    if (width * height > 1024 * 1024 || bitsPerComponent > 8) {        CGImageRelease(imageRef);        return image;    }    // CGImageGetBytesPerRow() calculates incorrectly in iOS 5.0, so defer to CGBitmapContextCreate    size_t bytesPerRow = 0;    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();    CGColorSpaceModel colorSpaceModel = CGColorSpaceGetModel(colorSpace);    CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);    if (colorSpaceModel == kCGColorSpaceModelRGB) {        uint32_t alpha = (bitmapInfo & kCGBitmapAlphaInfoMask);#pragma clang diagnostic push#pragma clang diagnostic ignored "-Wassign-enum"        if (alpha == kCGImageAlphaNone) {            bitmapInfo &= ~kCGBitmapAlphaInfoMask;            bitmapInfo |= kCGImageAlphaNoneSkipFirst;        } else if (!(alpha == kCGImageAlphaNoneSkipFirst || alpha == kCGImageAlphaNoneSkipLast)) {            bitmapInfo &= ~kCGBitmapAlphaInfoMask;            bitmapInfo |= kCGImageAlphaPremultipliedFirst;        }#pragma clang diagnostic pop    }    CGContextRef context = CGBitmapContextCreate(NULL, width, height, bitsPerComponent, bytesPerRow, colorSpace, bitmapInfo);    CGColorSpaceRelease(colorSpace);    if (!context) {        CGImageRelease(imageRef);        return image;    }    CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, width, height), imageRef);    CGImageRef inflatedImageRef = CGBitmapContextCreateImage(context);    CGContextRelease(context);    UIImage *inflatedImage = [[UIImage alloc] initWithCGImage:inflatedImageRef scale:scale orientation:image.imageOrientation];    CGImageRelease(inflatedImageRef);    CGImageRelease(imageRef);    return inflatedImage;}#endif第二种:直接通过Data转为imagestatic UIImage * AFImageWithDataAtScale(NSData *data, CGFloat scale) {    UIImage *image = [UIImage af_safeImageWithData:data];    if (image.images) {        return image;    }    return [[UIImage alloc] initWithCGImage:[image CGImage] scale:scale orientation:image.imageOrientation];}static NSLock* imageLock = nil;+ (UIImage *)af_safeImageWithData:(NSData *)data {    UIImage* image = nil;    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{        imageLock = [[NSLock alloc] init];    });    [imageLock lock];    image = [UIImage imageWithData:data];    [imageLock unlock];    return image;}

AFCompoundResponseSerializer类
如果返回的类型不确定就用这个方法先去确定类型找到合适的Serializer,然后再进行处理

- (id)responseObjectForResponse:(NSURLResponse *)response                           data:(NSData *)data                          error:(NSError *__autoreleasing *)error{    // 可能确实不能确定返回的responsed的content-type,此时可以使用AFCompoundResponseSerializer    // 总会找到合适的Serializer    for (id <AFURLResponseSerialization> serializer in self.responseSerializers) {        if (![serializer isKindOfClass:[AFHTTPResponseSerializer class]]) {            continue;        }        NSError *serializerError = nil;        id responseObject = [serializer responseObjectForResponse:response data:data error:&serializerError];        if (responseObject) {            if (error) {                *error = AFErrorWithUnderlyingError(serializerError, *error);            }            return responseObject;        }    }    return [super responseObjectForResponse:response data:data error:error];}

到此为止AFNetworking中对请求和响应的序列化操作结束,下面就是最重要的请求的方式。

1 0
原创粉丝点击