AFNetWorking 的简单使用

由于ASIHTTPRequest 不再更新了,不能使用block感觉不太好用;最后选择了AFNetWorking,并做了进一步的封装。


需要导入的framework:CFNetworkSecuritySystemConfigurationMobileCoreServices


GitHub:https://github.com/AFNetworking/AFNetworking


最新的版本为2.0支持iOS 6.0以上系统,在iOS 5上可能报错:Property with 'retain (or strong)' attribute must be of object type


下面是封装的类:


//  HttpManager.h

//
//  HttpManager.h
//  HLMagic
//
//  Created by marujun on 14-1-17.
//  Copyright (c) 2014年 jizhi. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonDigest.h>
#import "AFNetworking.h"
#import "Reachability.h"

@interface NSString (HttpManager)
- (NSString *)md5;
- (NSString *)encode;
- (NSString *)decode;
- (NSString *)object;
@end

@interface NSObject (HttpManager)
- (NSString *)json;
@end

@interface HttpManager : NSObject

+ (HttpManager *)defaultManager;

/*  -------判断当前的网络类型----------
 1、NotReachable     - 没有网络连接
 2、ReachableViaWWAN - 移动网络(2G、3G)
 3、ReachableViaWiFi - WIFI网络
 */
+ (NetworkStatus)networkStatus;

//GET 请求
- (void)getRequestToUrl:(NSString *)url params:(NSDictionary *)params complete:(void (^)(BOOL successed, NSDictionary *result))complete;
- (void)getCacheToUrl:(NSString *)url params:(NSDictionary *)params complete:(void (^)(BOOL successed, NSDictionary *result))complete;  //请求失败时使用缓存数据

//POST 请求
- (void)postRequestToUrl:(NSString *)url params:(NSDictionary *)params complete:(void (^)(BOOL successed, NSDictionary *result))complete;

/*
 files : 需要上传的文件数组,数组里为多个字典
 字典里的key:
 1、name: 文件名称(如:demo.jpg)
 2、file: 文件   (支持四种数据类型:NSData、UIImage、NSURL、NSString)NSURL、NSString为文件路径
 3、type: 文件类型(默认:image/jpeg)
 示例: @[@{@"file":_headImg.currentBackgroundImage,@"name":@"head.jpg"}];
 */

//AFHTTPRequestOperation可以暂停、重新开启、取消 [operation pause]、[operation resume];、[operation cancel];
- (AFHTTPRequestOperation *)uploadToUrl:(NSString *)url
                                 params:(NSDictionary *)params
                                  files:(NSArray *)files
                               complete:(void (^)(BOOL successed, NSDictionary *result))complete;


//可以查看进度 process_block
- (AFHTTPRequestOperation *)uploadToUrl:(NSString *)url
                                 params:(NSDictionary *)params
                                  files:(NSArray *)files
                                process:(void (^)(NSInteger writedBytes, NSInteger totalBytes))process
                               complete:(void (^)(BOOL successed, NSDictionary *result))complete;
/*
 filePath : 下载文件的存储路径
 response : 接口返回的不是文件而是json数据
 process  : 进度
 */
- (AFHTTPRequestOperation *)downloadFromUrl:(NSString *)url
                                   filePath:(NSString *)filePath
                                   complete:(void (^)(BOOL successed, NSDictionary *response))complete;

- (AFHTTPRequestOperation *)downloadFromUrl:(NSString *)url
                                     params:(NSDictionary *)params
                                   filePath:(NSString *)filePath
                                    process:(void (^)(NSInteger readBytes, NSInteger totalBytes))process
                                   complete:(void (^)(BOOL successed, NSDictionary *response))complete;

@end


// "HttpManager.m"

//
//  HttpManager.m
//  HLMagic
//
//  Created by marujun on 14-1-17.
//  Copyright (c) 2014年 jizhi. All rights reserved.
//

#import "HttpManager.h"

@implementation NSString (HttpManager)
- (NSString *)md5
{
    if(self == nil || [self length] == 0){
        return nil;
    }
    const char *value = [self UTF8String];
    
    unsigned char outputBuffer[CC_MD5_DIGEST_LENGTH];
    CC_MD5(value, (CC_LONG)strlen(value), outputBuffer);
    
    NSMutableString *outputString = [[NSMutableString alloc] initWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
    for(NSInteger count = 0; count < CC_MD5_DIGEST_LENGTH; count++){
        [outputString appendFormat:@"%02x",outputBuffer[count]];
    }
    
    return outputString;
}
- (NSString *)encode
{
    NSString *outputStr = (NSString *)
    CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
                                                              (CFStringRef)self,
                                                              NULL,
                                                              NULL,
                                                              kCFStringEncodingUTF8));
    return outputStr;
}
- (NSString *)decode
{
    NSMutableString *outputStr = [NSMutableString stringWithString:self];
    [outputStr replaceOccurrencesOfString:@"+" withString:@" " options:NSLiteralSearch range:NSMakeRange(0, [outputStr length])];
    return [outputStr stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
}
- (id)object
{
    id object = nil;
    @try {
        NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding];;
        object = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
    }
    @catch (NSException *exception) {
        NSLog(@"%s [Line %d] JSON字符串转换成对象出错了-->\n%@",__PRETTY_FUNCTION__, __LINE__,exception);
    }
    @finally {
    }
    return object;
}
@end
@implementation NSObject (HttpManager)
- (NSString *)json
{
    NSString *jsonStr = @"";
    @try {
        NSData *jsonData = [NSJSONSerialization dataWithJSONObject:self options:0 error:nil];
        jsonStr = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    }
    @catch (NSException *exception) {
        NSLog(@"%s [Line %d] 对象转换成JSON字符串出错了-->\n%@",__PRETTY_FUNCTION__, __LINE__,exception);
    }
    @finally {
    }
    return jsonStr;
}
@end

@interface HttpManager ()
{
    AFHTTPRequestOperationManager *operationManager;
}
@end

@implementation HttpManager

- (id)init{
    self = [super init];
	if (self) {
        operationManager = [AFHTTPRequestOperationManager manager];
        operationManager.responseSerializer.acceptableContentTypes = nil;
        
        NSURLCache *urlCache = [NSURLCache sharedURLCache];
        [urlCache setMemoryCapacity:5*1024*1024];  /* 设置缓存的大小为5M*/
        [NSURLCache setSharedURLCache:urlCache];
    }
    return self;
}


+ (HttpManager *)defaultManager
{
    static dispatch_once_t pred = 0;
    __strong static id defaultHttpManager = nil;
    dispatch_once( &pred, ^{
        defaultHttpManager = [[self alloc] init];
    });
    return defaultHttpManager;
}

- (void)getRequestToUrl:(NSString *)url params:(NSDictionary *)params complete:(void (^)(BOOL successed, NSDictionary *result))complete
{
    [self requestToUrl:url method:@"GET" useCache:NO params:params complete:complete];
}

- (void)getCacheToUrl:(NSString *)url params:(NSDictionary *)params complete:(void (^)(BOOL successed, NSDictionary *result))complete
{
    [self requestToUrl:url method:@"GET" useCache:YES params:params complete:complete];
}

- (void)postRequestToUrl:(NSString *)url params:(NSDictionary *)params complete:(void (^)(BOOL successed, NSDictionary *result))complete
{
    [self requestToUrl:url method:@"POST" useCache:NO params:params complete:complete];
}

- (void)requestToUrl:(NSString *)url method:(NSString *)method useCache:(BOOL)useCache
              params:(NSDictionary *)params complete:(void (^)(BOOL successed, NSDictionary *result))complete
{
    params = [[HttpManager getRequestBodyWithParams:params] copy];
    
    AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer];
    NSMutableURLRequest *request = [serializer requestWithMethod:method URLString:url parameters:params error:nil];
    
    [request setTimeoutInterval:10];
    if (useCache) {
        [request setCachePolicy:NSURLRequestReturnCacheDataElseLoad];
    }
    
    void (^requestSuccessBlock)(AFHTTPRequestOperation *operation, id responseObject) = ^(AFHTTPRequestOperation *operation, id responseObject) {
        [self showMessageWithOperation:operation method:method params:params];
        
        complete ? complete(true,responseObject) : nil;
    };
    void (^requestFailureBlock)(AFHTTPRequestOperation *operation, NSError *error) = ^(AFHTTPRequestOperation *operation, NSError *error) {
        [self showMessageWithOperation:operation method:method params:params];
        
        complete ? complete(false,nil) : nil;
    };
    
    AFHTTPRequestOperation *operation = nil;
    if (useCache) {
        operation = [self cacheOperationWithRequest:request success:requestSuccessBlock failure:requestFailureBlock];
    }else{
        operation = [operationManager HTTPRequestOperationWithRequest:request success:requestSuccessBlock failure:requestFailureBlock];
    }
    [operationManager.operationQueue addOperation:operation];
}

- (AFHTTPRequestOperation *)cacheOperationWithRequest:(NSURLRequest *)urlRequest
                                              success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
                                              failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
    AFHTTPRequestOperation *operation = [operationManager HTTPRequestOperationWithRequest:urlRequest success:^(AFHTTPRequestOperation *operation, id responseObject){
        NSCachedURLResponse *cachedURLResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:urlRequest];
        
        //store in cache
        cachedURLResponse = [[NSCachedURLResponse alloc] initWithResponse:operation.response data:operation.responseData userInfo:nil storagePolicy:NSURLCacheStorageAllowed];
        [[NSURLCache sharedURLCache] storeCachedResponse:cachedURLResponse forRequest:urlRequest];
        
        success(operation,responseObject);
        
    }failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        if (error.code == kCFURLErrorNotConnectedToInternet) {
            NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:urlRequest];
            if (cachedResponse != nil && [[cachedResponse data] length] > 0) {
                success(operation, cachedResponse.data);
            } else {
                failure(operation, error);
            }
        } else {
            failure(operation, error);
        }
    }];
    
    return operation;
}

- (AFHTTPRequestOperation *)uploadToUrl:(NSString *)url
                                 params:(NSDictionary *)params
                                  files:(NSArray *)files
                               complete:(void (^)(BOOL successed, NSDictionary *result))complete
{
    return [self uploadToUrl:url params:params files:files process:nil complete:complete];
}

- (AFHTTPRequestOperation *)uploadToUrl:(NSString *)url
                                 params:(NSDictionary *)params
                                  files:(NSArray *)files
                                process:(void (^)(NSInteger writedBytes, NSInteger totalBytes))process
                               complete:(void (^)(BOOL successed, NSDictionary *result))complete
{
    params = [[HttpManager getRequestBodyWithParams:params] copy];
    FLOG(@"post request url:  %@  \npost params:  %@",url,params);
    
    AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer];
    
    NSMutableURLRequest *request = [serializer multipartFormRequestWithMethod:@"POST" URLString:url parameters:params constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
        for (NSDictionary *fileItem in files) {
            id value = [fileItem objectForKey:@"file"];    //支持四种数据类型:NSData、UIImage、NSURL、NSString
            NSString *name = @"file";                                   //字段名称
            NSString *fileName = [fileItem objectForKey:@"name"];       //文件名称
            NSString *mimeType = [fileItem objectForKey:@"type"];       //文件类型
            mimeType = mimeType ? mimeType : @"image/jpeg";
            
            if ([value isKindOfClass:[NSData class]]) {
                [formData appendPartWithFileData:value name:name fileName:fileName mimeType:mimeType];
            }else if ([value isKindOfClass:[UIImage class]]) {
                if (UIImagePNGRepresentation(value)) {  //返回为png图像。
                    [formData appendPartWithFileData:UIImagePNGRepresentation(value) name:name fileName:fileName mimeType:mimeType];
                }else {   //返回为JPEG图像。
                    [formData appendPartWithFileData:UIImageJPEGRepresentation(value, 0.5) name:name fileName:fileName mimeType:mimeType];
                }
            }else if ([value isKindOfClass:[NSURL class]]) {
                [formData appendPartWithFileURL:value name:name fileName:fileName mimeType:mimeType error:nil];
            }else if ([value isKindOfClass:[NSString class]]) {
                [formData appendPartWithFileURL:[NSURL URLWithString:value]  name:name fileName:fileName mimeType:mimeType error:nil];
            }
        }
    } error:nil];
    
    AFHTTPRequestOperation *operation = nil;
    operation = [operationManager HTTPRequestOperationWithRequest:request
                                                 success:^(AFHTTPRequestOperation *operation, id responseObject) {
                                                     FLOG(@"post responseObject:  %@",responseObject);
                                                     if (complete) {
                                                         complete(true,responseObject);
                                                     }
                                                 } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                                                     FLOG(@"post error :  %@",error);
                                                     if (complete) {
                                                         complete(false,nil);
                                                     }
                                                 }];
    
    [operation setUploadProgressBlock:^(NSUInteger bytesWritten, NSInteger totalBytesWritten, NSInteger totalBytesExpectedToWrite) {
        FLOG(@"upload process: %.2d%% (%ld/%ld)",100*totalBytesWritten/totalBytesExpectedToWrite,(long)totalBytesWritten,(long)totalBytesExpectedToWrite);
        if (process) {
            process(totalBytesWritten,totalBytesExpectedToWrite);
        }
    }];
    [operation start];
    
    return operation;
}

- (AFHTTPRequestOperation *)downloadFromUrl:(NSString *)url
                                   filePath:(NSString *)filePath
                                   complete:(void (^)(BOOL successed, NSDictionary *response))complete
{
    return [self downloadFromUrl:url params:nil filePath:filePath process:nil complete:complete];
}

- (AFHTTPRequestOperation *)downloadFromUrl:(NSString *)url
                                     params:(NSDictionary *)params
                                   filePath:(NSString *)filePath
                                    process:(void (^)(NSInteger readBytes, NSInteger totalBytes))process
                                   complete:(void (^)(BOOL successed, NSDictionary *response))complete
{
    params = [[HttpManager getRequestBodyWithParams:params] copy];
    
    AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer];
    NSMutableURLRequest *request = [serializer requestWithMethod:@"GET" URLString:url parameters:params error:nil];
    FLOG(@"get request url: %@",[request.URL.absoluteString decode]);
    
    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    operation.responseSerializer.acceptableContentTypes = nil;
    
    NSString *tmpPath = [filePath stringByAppendingString:@".tmp"];
    operation.outputStream=[[NSOutputStream alloc] initToFileAtPath:tmpPath append:NO];
    
    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSArray *mimeTypeArray = @[@"text/html", @"application/json"];
        NSError *moveError = nil;
        if ([mimeTypeArray containsObject:operation.response.MIMEType]) {
            //返回的是json格式数据
            responseObject = [NSData dataWithContentsOfFile:tmpPath];
            responseObject = [NSJSONSerialization JSONObjectWithData:responseObject options:2 error:nil];
            [[NSFileManager defaultManager] removeItemAtPath:tmpPath error:nil];
            FLOG(@"get responseObject:  %@",responseObject);
        }else{
            [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];
            [[NSFileManager defaultManager] moveItemAtPath:tmpPath toPath:filePath error:&moveError];
        }
        
        if (complete && !moveError) {
            complete(true,responseObject);
        }else{
            complete?complete(false,responseObject):nil;
        }
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        FLOG(@"get error :  %@",error);
        [[NSFileManager defaultManager] removeItemAtPath:tmpPath error:nil];
        if (complete) {
            complete(false,nil);
        }
    }];
    [operation setDownloadProgressBlock:^(NSUInteger bytesRead, NSInteger totalBytesRead, NSInteger totalBytesExpectedToRead) {
        FLOG(@"download process: %.2d%% (%ld/%ld)",100*totalBytesRead/totalBytesExpectedToRead,(long)totalBytesRead,(long)totalBytesExpectedToRead);
        if (process) {
            process(totalBytesRead,totalBytesExpectedToRead);
        }
    }];
    
    [operation start];
    
    return operation;
}

+ (NSMutableDictionary *)getRequestBodyWithParams:(NSDictionary *)params
{
    NSMutableDictionary *requestBody = params?[params mutableCopy]:[[NSMutableDictionary alloc] init];
    
    for (NSString *key in [params allKeys]){
        id value = [params objectForKey:key];
        if ([value isKindOfClass:[NSDate class]]) {
            [requestBody setValue:@([value timeIntervalSince1970]*1000) forKey:key];
        }
        if ([value isKindOfClass:[NSDictionary class]] || [value isKindOfClass:[NSArray class]]) {
            [requestBody setValue:[value json] forKey:key];
        }
    }
    
    NSString *token = [[NSUserDefaults standardUserDefaults] objectForKey:@"token"];
    if (token){
        [requestBody setObject:token forKey:@"token"];
    }
    [requestBody setObject:@"ios" forKey:@"genus"];
    
    return requestBody;
}

+ (NetworkStatus)networkStatus
{
    Reachability *reachability = [Reachability reachabilityWithHostname:@"www.apple.com"];
    // NotReachable     - 没有网络连接
    // ReachableViaWWAN - 移动网络(2G、3G)
    // ReachableViaWiFi - WIFI网络
    return [reachability currentReachabilityStatus];
}


- (void)showMessageWithOperation:(AFHTTPRequestOperation *)operation method:(NSString *)method params:(NSDictionary *)params
{
    NSString *urlAbsoluteString = [operation.request.URL.absoluteString decode];
    if ([[method uppercaseString] isEqualToString:@"GET"]) {
        FLOG(@"get request url:  %@  \n",urlAbsoluteString);
    }else{
        FLOG(@"%@ request url:  %@  \npost params:  %@\n",[method lowercaseString],urlAbsoluteString,params);
    }
    if (operation.error) {
        FLOG(@"%@ error :  %@",[method lowercaseString],operation.error);
    }else{
        FLOG(@"%@ responseObject:  %@",[method lowercaseString],operation.responseObject);
    }
    
//    //只显示一部分url
//    NSArray *ignordUrls = @[url_originalDataDownload,url_originalDataUpload,url_originalDataUploadFinished,url_getEarliestOriginalData,url_newVersion,
//                            url_saveSyncFailInfo];
//    for (NSString *ignordUrl in ignordUrls) {
//        if ([urlAbsoluteString rangeOfString:ignordUrl].length) {
//            return;
//        }
//    }
//    //弹出网络提示
//	if (!operation.error) {
//		if ([operation.responseObject objectForKey:@"msg"] && [[operation.responseObject objectForKey:@"msg"] length]) {
//			[KeyWindow showAlertMessage:[operation.responseObject objectForKey:@"msg"] callback:nil];
//		}
//	}
//	else {
//        if (operation.error.code == kCFURLErrorNotConnectedToInternet) {
//            [KeyWindow showAlertMessage:@"您已断开网络连接" callback:nil];
//        } else {
//            [KeyWindow showAlertMessage:@"服务器忙,请稍后再试" callback:nil];
//        }
//	}
}

@end


图片缓存类,用于缓存图片;并写了UIImageView和UIButton的扩展方法;可直接设置其对应图片的URL。


//  ImageCache.h

//
//  ImageCache.h
//  CoreDataUtil
//
//  Created by marujun on 14-1-18.
//  Copyright (c) 2014年 jizhi. All rights reserved.
//

#import <UIKit/UIKit.h>
#import <UIKit/UIImageView.h>
#import <UIKit/UIButton.h>
#import <objc/runtime.h>

#define ADD_DYNAMIC_PROPERTY(PROPERTY_TYPE,PROPERTY_NAME,SETTER_NAME) \
@dynamic PROPERTY_NAME ; \
static char kProperty##PROPERTY_NAME; \
- ( PROPERTY_TYPE ) PROPERTY_NAME{ \
return ( PROPERTY_TYPE ) objc_getAssociatedObject(self, &(kProperty##PROPERTY_NAME ) ); \
} \
- (void) SETTER_NAME :( PROPERTY_TYPE ) PROPERTY_NAME{ \
objc_setAssociatedObject(self, &kProperty##PROPERTY_NAME , PROPERTY_NAME , OBJC_ASSOCIATION_RETAIN); \
} \

@interface UIImage (ImageCache)
@property(nonatomic, strong)NSString *lastCacheUrl;

/* ********************----------*****************************
 1、UIImage 的扩展方法,用于缓存图片;如果图片已下载则使用本地图片
 2、下载完成之后会执行回调,并可查看下载进度
 ********************----------******************************/

+ (void)imageWithURL:(NSString *)url callback:(void(^)(UIImage *image))callback;

+ (void)imageWithURL:(NSString *)url
             process:(void (^)(NSInteger readBytes, NSInteger totalBytes))process
            callback:(void(^)(UIImage *image))callback;

/*通过URL获取缓存图片在本地对应的路径*/
+ (NSString *)getImagePathWithURL:(NSString *)url;

@end

@interface UIImageView (ImageCache)
@property(nonatomic, strong)NSString *lastCacheUrl;

/*设置UIImageView的图片的URL,下载失败设置图片为空*/
- (void)setImageURL:(NSString *)url;

/*设置UIImageView的图片的URL,下载失败则使用默认图片设置*/
- (void)setImageURL:(NSString *)url defaultImage:(UIImage *)defaultImage;

/*设置UIImageView的图片的URL,下载完成之后先设置图片然后执行回调函数*/
- (void)setImageURL:(NSString *)url callback:(void(^)(UIImage *image))callback;

@end

@interface UIButton (ImageCache)
@property(nonatomic, strong)NSString *lastCacheUrl;

/*设置按钮的图片的URL,下载失败设置图片为空*/
- (void)setImageURL:(NSString *)url forState:(UIControlState)state;

/*设置按钮的图片的URL,下载失败则使用默认图片设置*/
- (void)setImageURL:(NSString *)url forState:(UIControlState)state defaultImage:(UIImage *)defaultImage;

/*设置按钮的图片的URL,下载完成之后先设置图片然后执行回调函数*/
- (void)setImageURL:(NSString *)url forState:(UIControlState)state callback:(void(^)(UIImage *image))callback;



/*设置按钮的背景图片的URL,下载失败设置图片为空*/
- (void)setBackgroundImageURL:(NSString *)url forState:(UIControlState)state;

/*设置按钮的背景图片的URL,下载失败则使用默认图片设置*/
- (void)setBackgroundImageURL:(NSString *)url forState:(UIControlState)state defaultImage:(UIImage *)defaultImage;

/*设置按钮的背景图片的URL,下载完成之后先设置图片然后执行回调函数*/
- (void)setBackgroundImageURL:(NSString *)url forState:(UIControlState)state callback:(void(^)(UIImage *image))callback;

@end


//  ImageCache.m

//
//  ImageCache.m
//  CoreDataUtil
//
//  Created by marujun on 14-1-18.
//  Copyright (c) 2014年 jizhi. All rights reserved.
//

#import "ImageCache.h"
#import "HttpManager.h"

static NSMutableArray *downloadTaskArray_ImageCache;
static BOOL isDownloading_ImageCache;

@implementation UIImage (ImageCache)
ADD_DYNAMIC_PROPERTY(NSString *,lastCacheUrl,setLastCacheUrl);

+ (void)imageWithURL:(NSString *)url callback:(void(^)(UIImage *image))callback
{
    [self imageWithURL:url process:nil callback:callback];
}

+ (void)imageWithURL:(NSString *)url
             process:(void (^)(NSInteger readBytes, NSInteger totalBytes))process
            callback:(void(^)(UIImage *image))callback
{
    if (!downloadTaskArray_ImageCache) {
        downloadTaskArray_ImageCache = [[NSMutableArray alloc] init];
    }
    
    NSString *filePath = [self getImagePathWithURL:url];
    
    if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
        UIImage *lastImage = [UIImage imageWithContentsOfFile:filePath];
        lastImage.lastCacheUrl = url?url:@"";
        callback ? callback(lastImage) : nil;
    }else{
        NSMutableDictionary *task = [[NSMutableDictionary alloc] init];
        url?[task setObject:url forKey:@"url"]:nil;
        process?[task setObject:process forKey:@"process"]:nil;
        callback?[task setObject:callback forKey:@"callback"]:nil;
        [downloadTaskArray_ImageCache addObject:task];
        
        [self startDownload];
    }
}

+ (void)startDownload
{
    if (downloadTaskArray_ImageCache.count && !isDownloading_ImageCache) {
        NSDictionary *lastObj = [downloadTaskArray_ImageCache lastObject];
        [self downloadWithURL:lastObj[@"url"] process:lastObj[@"process"] callback:lastObj[@"callback"]];
    }
}

+ (void)downloadWithURL:(NSString *)url
                process:(void (^)(NSInteger readBytes, NSInteger totalBytes))process
               callback:(void(^)(UIImage *image))callback
{
    NSString *filePath = [self getImagePathWithURL:url];
    NSMutableDictionary *task = [[NSMutableDictionary alloc] init];
    url?[task setObject:url forKey:@"url"]:nil;
    process?[task setObject:process forKey:@"process"]:nil;
    callback?[task setObject:callback forKey:@"callback"]:nil;
    isDownloading_ImageCache = true;
    
    if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
        UIImage *lastImage = [UIImage imageWithContentsOfFile:filePath];
        lastImage.lastCacheUrl = url?url:@"";
        callback ? callback(lastImage) : nil;
        
        [downloadTaskArray_ImageCache removeObject:task];
        isDownloading_ImageCache = false;
        [self startDownload];
    }else{
        [[HttpManager defaultManager] downloadFromUrl:url
                                               params:nil
                                             filePath:filePath
                                              process:process
                                             complete:^(BOOL successed, NSDictionary *result) {
                                                 if (callback) {
                                                     if (successed && !result) {
                                                         UIImage *lastImage = [UIImage imageWithContentsOfFile:filePath];
                                                         lastImage.lastCacheUrl = url?url:@"";
                                                         callback ? callback(lastImage) : nil;
                                                     }else{
                                                         callback(nil);
                                                     }
                                                 }
                                                 [downloadTaskArray_ImageCache removeObject:task];
                                                 isDownloading_ImageCache = false;
                                                 [self startDownload];
                                             }];
    }
}

+ (NSString *)getImagePathWithURL:(NSString *)url
{
    //先创建个缓存文件夹
    NSString *directory = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Caches/imgcache"];
    NSFileManager *defaultManager = [NSFileManager defaultManager];
    if (![defaultManager fileExistsAtPath:directory]) {
        [defaultManager createDirectoryAtPath:directory withIntermediateDirectories:YES attributes:nil error:nil];
    }
    
    return [directory stringByAppendingPathComponent:[url md5]];
}

@end

@implementation UIImageView (ImageCache)
ADD_DYNAMIC_PROPERTY(NSString *,lastCacheUrl,setLastCacheUrl);

- (void)setImageURL:(NSString *)url
{
    [self setImageURL:url callback:nil];
}
- (void)setImageURL:(NSString *)url defaultImage:(UIImage *)defaultImage
{
    defaultImage ? self.image=defaultImage : nil;
    self.lastCacheUrl = url;
    
    [UIImage imageWithURL:url callback:^(UIImage *image) {
        if ([image.lastCacheUrl isEqualToString:self.lastCacheUrl]) {
            image ? self.image=image : nil;
        }
    }];
}
- (void)setImageURL:(NSString *)url callback:(void(^)(UIImage *image))callback
{
    self.lastCacheUrl = url;
    
    [UIImage imageWithURL:url callback:^(UIImage *image) {
        if ([image.lastCacheUrl isEqualToString:self.lastCacheUrl]) {
            image ? self.image=image : nil;
        }
        callback ? callback(image) : nil;
    }];
}

@end

@implementation UIButton (ImageCache)
ADD_DYNAMIC_PROPERTY(NSString *,lastCacheUrl,setLastCacheUrl);

- (void)setImageURL:(NSString *)url forState:(UIControlState)state
{
    [self setImageURL:url forState:state defaultImage:nil];
}
- (void)setImageURL:(NSString *)url forState:(UIControlState)state defaultImage:(UIImage *)defaultImage
{
    defaultImage ? [self setImage:defaultImage forState:state] : nil;
    self.lastCacheUrl = url;
    
    [UIImage imageWithURL:url callback:^(UIImage *image) {
        if ([image.lastCacheUrl isEqualToString:self.lastCacheUrl]) {
            image ? [self setImage:image forState:state] : nil;
        }
    }];
}
- (void)setImageURL:(NSString *)url forState:(UIControlState)state callback:(void(^)(UIImage *image))callback
{
    self.lastCacheUrl = url;
    
    [UIImage imageWithURL:url callback:^(UIImage *image) {
        if ([image.lastCacheUrl isEqualToString:self.lastCacheUrl]) {
            image ? [self setImage:image forState:state] : nil;
        }
        callback ? callback(image) : nil;
    }];
}


- (void)setBackgroundImageURL:(NSString *)url forState:(UIControlState)state
{
    [self setBackgroundImageURL:url forState:state defaultImage:nil];
}
- (void)setBackgroundImageURL:(NSString *)url forState:(UIControlState)state defaultImage:(UIImage *)defaultImage
{
    defaultImage ? [self setBackgroundImage:defaultImage forState:state] : nil;
    self.lastCacheUrl = url;
    
    [UIImage imageWithURL:url callback:^(UIImage *image) {
        if ([image.lastCacheUrl isEqualToString:self.lastCacheUrl]) {
            image ? [self setBackgroundImage:image forState:state] : nil;
        }
    }];
}
- (void)setBackgroundImageURL:(NSString *)url forState:(UIControlState)state callback:(void(^)(UIImage *image))callback
{
    self.lastCacheUrl = url;
    
    [UIImage imageWithURL:url callback:^(UIImage *image) {
        if ([image.lastCacheUrl isEqualToString:self.lastCacheUrl]) {
            image ? [self setBackgroundImage:image forState:state] : nil;
        }
        callback ? callback(image) : nil;
    }];
}

@end




/*  使用示例 */
     NSString *url = @"http://b.hiphotos.baidu.com/image/w%3D2048/sign=4c2a6e019058d109c4e3aeb2e560cdbf/b812c8fcc3cec3fd6d7daa0ad488d43f87942709.jpg";
    
    //缓存图片
//    [UIImage imageWithURL:url process:^(NSInteger readBytes, NSInteger totalBytes) {
//        NSLog(@"下载进度 : %.0f%%",100*readBytes/totalBytes);
//    } callback:^(UIImage *image) {
//        NSLog(@"图片下载完成!");
//    }];
   
    //设置UIImageView的图片,下载失败则使用默认图片
    UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.view.bounds];
    [imageView setImageURL:url defaultImage:[UIImage imageNamed:@"default.png"]];
    imageView.contentMode = UIViewContentModeScaleAspectFit;
    [self.view addSubview:imageView];
    
    //设置UIButton的图片,下载失败则使用默认图片
    UIButton *button = [[UIButton alloc] initWithFrame:self.view.bounds];
    [button setImageURL:url forState:UIControlStateNormal defaultImage:[UIImage imageNamed:@"default.png"]];
    [self.view addSubview:button];

GitHub 地址:https://github.com/marujun/DataManager


你可能感兴趣的:(AFNetWorking 的简单使用)