AFNetWorking 的简单使用

时间:2024-08-01 18:35:08

转:http://blog.****.net/marujunyy/article/details/18424711

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

需要导入的framework:CFNetwork、Security、SystemConfiguration、MobileCoreServices

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

  1. //
  2. //  HttpManager.h
  3. //  HLMagic
  4. //
  5. //  Created by marujun on 14-1-17.
  6. //  Copyright (c) 2014年 jizhi. All rights reserved.
  7. //
  8. #import <Foundation/Foundation.h>
  9. #import <CommonCrypto/CommonDigest.h>
  10. #import "AFNetworking.h"
  11. #import "Reachability.h"
  12. @interface NSString (HttpManager)
  13. - (NSString *)md5;
  14. - (NSString *)encode;
  15. - (NSString *)decode;
  16. - (NSString *)object;
  17. @end
  18. @interface NSObject (HttpManager)
  19. - (NSString *)json;
  20. @end
  21. @interface HttpManager : NSObject
  22. + (HttpManager *)defaultManager;
  23. /*  -------判断当前的网络类型----------
  24. 1、NotReachable     - 没有网络连接
  25. 2、ReachableViaWWAN - 移动网络(2G、3G)
  26. 3、ReachableViaWiFi - WIFI网络
  27. */
  28. + (NetworkStatus)networkStatus;
  29. //GET 请求
  30. - (void)getRequestToUrl:(NSString *)url params:(NSDictionary *)params complete:(void (^)(BOOL successed, NSDictionary *result))complete;
  31. - (void)getCacheToUrl:(NSString *)url params:(NSDictionary *)params complete:(void (^)(BOOL successed, NSDictionary *result))complete;  //请求失败时使用缓存数据
  32. //POST 请求
  33. - (void)postRequestToUrl:(NSString *)url params:(NSDictionary *)params complete:(void (^)(BOOL successed, NSDictionary *result))complete;
  34. /*
  35. files : 需要上传的文件数组,数组里为多个字典
  36. 字典里的key:
  37. 1、name: 文件名称(如:demo.jpg)
  38. 2、file: 文件   (支持四种数据类型:NSData、UIImage、NSURL、NSString)NSURL、NSString为文件路径
  39. 3、type: 文件类型(默认:image/jpeg)
  40. 示例: @[@{@"file":_headImg.currentBackgroundImage,@"name":@"head.jpg"}];
  41. */
  42. //AFHTTPRequestOperation可以暂停、重新开启、取消 [operation pause]、[operation resume];、[operation cancel];
  43. - (AFHTTPRequestOperation *)uploadToUrl:(NSString *)url
  44. params:(NSDictionary *)params
  45. files:(NSArray *)files
  46. complete:(void (^)(BOOL successed, NSDictionary *result))complete;
  47. //可以查看进度 process_block
  48. - (AFHTTPRequestOperation *)uploadToUrl:(NSString *)url
  49. params:(NSDictionary *)params
  50. files:(NSArray *)files
  51. process:(void (^)(NSInteger writedBytes, NSInteger totalBytes))process
  52. complete:(void (^)(BOOL successed, NSDictionary *result))complete;
  53. /*
  54. filePath : 下载文件的存储路径
  55. response : 接口返回的不是文件而是json数据
  56. process  : 进度
  57. */
  58. - (AFHTTPRequestOperation *)downloadFromUrl:(NSString *)url
  59. filePath:(NSString *)filePath
  60. complete:(void (^)(BOOL successed, NSDictionary *response))complete;
  61. - (AFHTTPRequestOperation *)downloadFromUrl:(NSString *)url
  62. params:(NSDictionary *)params
  63. filePath:(NSString *)filePath
  64. process:(void (^)(NSInteger readBytes, NSInteger totalBytes))process
  65. complete:(void (^)(BOOL successed, NSDictionary *response))complete;
  66. @end

// "HttpManager.m"

  1. //
  2. //  HttpManager.m
  3. //  HLMagic
  4. //
  5. //  Created by marujun on 14-1-17.
  6. //  Copyright (c) 2014年 jizhi. All rights reserved.
  7. //
  8. #import "HttpManager.h"
  9. @implementation NSString (HttpManager)
  10. - (NSString *)md5
  11. {
  12. if(self == nil || [self length] == 0){
  13. return nil;
  14. }
  15. const char *value = [self UTF8String];
  16. unsigned char outputBuffer[CC_MD5_DIGEST_LENGTH];
  17. CC_MD5(value, (CC_LONG)strlen(value), outputBuffer);
  18. NSMutableString *outputString = [[NSMutableString alloc] initWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
  19. for(NSInteger count = 0; count < CC_MD5_DIGEST_LENGTH; count++){
  20. [outputString appendFormat:@"%02x",outputBuffer[count]];
  21. }
  22. return outputString;
  23. }
  24. - (NSString *)encode
  25. {
  26. NSString *outputStr = (NSString *)
  27. CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
  28. (CFStringRef)self,
  29. NULL,
  30. NULL,
  31. kCFStringEncodingUTF8));
  32. return outputStr;
  33. }
  34. - (NSString *)decode
  35. {
  36. NSMutableString *outputStr = [NSMutableString stringWithString:self];
  37. [outputStr replaceOccurrencesOfString:@"+" withString:@" " options:NSLiteralSearch range:NSMakeRange(0, [outputStr length])];
  38. return [outputStr stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
  39. }
  40. - (id)object
  41. {
  42. id object = nil;
  43. @try {
  44. NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding];;
  45. object = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
  46. }
  47. @catch (NSException *exception) {
  48. NSLog(@"%s [Line %d] JSON字符串转换成对象出错了-->\n%@",__PRETTY_FUNCTION__, __LINE__,exception);
  49. }
  50. @finally {
  51. }
  52. return object;
  53. }
  54. @end
  55. @implementation NSObject (HttpManager)
  56. - (NSString *)json
  57. {
  58. NSString *jsonStr = @"";
  59. @try {
  60. NSData *jsonData = [NSJSONSerialization dataWithJSONObject:self options:0 error:nil];
  61. jsonStr = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
  62. }
  63. @catch (NSException *exception) {
  64. NSLog(@"%s [Line %d] 对象转换成JSON字符串出错了-->\n%@",__PRETTY_FUNCTION__, __LINE__,exception);
  65. }
  66. @finally {
  67. }
  68. return jsonStr;
  69. }
  70. @end
  71. @interface HttpManager ()
  72. {
  73. AFHTTPRequestOperationManager *operationManager;
  74. }
  75. @end
  76. @implementation HttpManager
  77. - (id)init{
  78. self = [super init];
  79. if (self) {
  80. operationManager = [AFHTTPRequestOperationManager manager];
  81. operationManager.responseSerializer.acceptableContentTypes = nil;
  82. NSURLCache *urlCache = [NSURLCache sharedURLCache];
  83. [urlCache setMemoryCapacity:5*1024*1024];  /* 设置缓存的大小为5M*/
  84. [NSURLCache setSharedURLCache:urlCache];
  85. }
  86. return self;
  87. }
  88. + (HttpManager *)defaultManager
  89. {
  90. static dispatch_once_t pred = 0;
  91. __strong static id defaultHttpManager = nil;
  92. dispatch_once( &pred, ^{
  93. defaultHttpManager = [[self alloc] init];
  94. });
  95. return defaultHttpManager;
  96. }
  97. - (void)getRequestToUrl:(NSString *)url params:(NSDictionary *)params complete:(void (^)(BOOL successed, NSDictionary *result))complete
  98. {
  99. [self requestToUrl:url method:@"GET" useCache:NO params:params complete:complete];
  100. }
  101. - (void)getCacheToUrl:(NSString *)url params:(NSDictionary *)params complete:(void (^)(BOOL successed, NSDictionary *result))complete
  102. {
  103. [self requestToUrl:url method:@"GET" useCache:YES params:params complete:complete];
  104. }
  105. - (void)postRequestToUrl:(NSString *)url params:(NSDictionary *)params complete:(void (^)(BOOL successed, NSDictionary *result))complete
  106. {
  107. [self requestToUrl:url method:@"POST" useCache:NO params:params complete:complete];
  108. }
  109. - (void)requestToUrl:(NSString *)url method:(NSString *)method useCache:(BOOL)useCache
  110. params:(NSDictionary *)params complete:(void (^)(BOOL successed, NSDictionary *result))complete
  111. {
  112. params = [[HttpManager getRequestBodyWithParams:params] copy];
  113. AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer];
  114. NSMutableURLRequest *request = [serializer requestWithMethod:method URLString:url parameters:params error:nil];
  115. [request setTimeoutInterval:10];
  116. if (useCache) {
  117. [request setCachePolicy:NSURLRequestReturnCacheDataElseLoad];
  118. }
  119. void (^requestSuccessBlock)(AFHTTPRequestOperation *operation, id responseObject) = ^(AFHTTPRequestOperation *operation, id responseObject) {
  120. [self showMessageWithOperation:operation method:method params:params];
  121. complete ? complete(true,responseObject) : nil;
  122. };
  123. void (^requestFailureBlock)(AFHTTPRequestOperation *operation, NSError *error) = ^(AFHTTPRequestOperation *operation, NSError *error) {
  124. [self showMessageWithOperation:operation method:method params:params];
  125. complete ? complete(false,nil) : nil;
  126. };
  127. AFHTTPRequestOperation *operation = nil;
  128. if (useCache) {
  129. operation = [self cacheOperationWithRequest:request success:requestSuccessBlock failure:requestFailureBlock];
  130. }else{
  131. operation = [operationManager HTTPRequestOperationWithRequest:request success:requestSuccessBlock failure:requestFailureBlock];
  132. }
  133. [operationManager.operationQueue addOperation:operation];
  134. }
  135. - (AFHTTPRequestOperation *)cacheOperationWithRequest:(NSURLRequest *)urlRequest
  136. success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
  137. failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
  138. {
  139. AFHTTPRequestOperation *operation = [operationManager HTTPRequestOperationWithRequest:urlRequest success:^(AFHTTPRequestOperation *operation, id responseObject){
  140. NSCachedURLResponse *cachedURLResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:urlRequest];
  141. //store in cache
  142. cachedURLResponse = [[NSCachedURLResponse alloc] initWithResponse:operation.response data:operation.responseData userInfo:nil storagePolicy:NSURLCacheStorageAllowed];
  143. [[NSURLCache sharedURLCache] storeCachedResponse:cachedURLResponse forRequest:urlRequest];
  144. success(operation,responseObject);
  145. }failure:^(AFHTTPRequestOperation *operation, NSError *error) {
  146. if (error.code == kCFURLErrorNotConnectedToInternet) {
  147. NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:urlRequest];
  148. if (cachedResponse != nil && [[cachedResponse data] length] > 0) {
  149. success(operation, cachedResponse.data);
  150. } else {
  151. failure(operation, error);
  152. }
  153. } else {
  154. failure(operation, error);
  155. }
  156. }];
  157. return operation;
  158. }
  159. - (AFHTTPRequestOperation *)uploadToUrl:(NSString *)url
  160. params:(NSDictionary *)params
  161. files:(NSArray *)files
  162. complete:(void (^)(BOOL successed, NSDictionary *result))complete
  163. {
  164. return [self uploadToUrl:url params:params files:files process:nil complete:complete];
  165. }
  166. - (AFHTTPRequestOperation *)uploadToUrl:(NSString *)url
  167. params:(NSDictionary *)params
  168. files:(NSArray *)files
  169. process:(void (^)(NSInteger writedBytes, NSInteger totalBytes))process
  170. complete:(void (^)(BOOL successed, NSDictionary *result))complete
  171. {
  172. params = [[HttpManager getRequestBodyWithParams:params] copy];
  173. FLOG(@"post request url:  %@  \npost params:  %@",url,params);
  174. AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer];
  175. NSMutableURLRequest *request = [serializer multipartFormRequestWithMethod:@"POST" URLString:url parameters:params constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
  176. for (NSDictionary *fileItem in files) {
  177. id value = [fileItem objectForKey:@"file"];    //支持四种数据类型:NSData、UIImage、NSURL、NSString
  178. NSString *name = @"file";                                   //字段名称
  179. NSString *fileName = [fileItem objectForKey:@"name"];       //文件名称
  180. NSString *mimeType = [fileItem objectForKey:@"type"];       //文件类型
  181. mimeType = mimeType ? mimeType : @"image/jpeg";
  182. if ([value isKindOfClass:[NSData class]]) {
  183. [formData appendPartWithFileData:value name:name fileName:fileName mimeType:mimeType];
  184. }else if ([value isKindOfClass:[UIImage class]]) {
  185. if (UIImagePNGRepresentation(value)) {  //返回为png图像。
  186. [formData appendPartWithFileData:UIImagePNGRepresentation(value) name:name fileName:fileName mimeType:mimeType];
  187. }else {   //返回为JPEG图像。
  188. [formData appendPartWithFileData:UIImageJPEGRepresentation(value, 0.5) name:name fileName:fileName mimeType:mimeType];
  189. }
  190. }else if ([value isKindOfClass:[NSURL class]]) {
  191. [formData appendPartWithFileURL:value name:name fileName:fileName mimeType:mimeType error:nil];
  192. }else if ([value isKindOfClass:[NSString class]]) {
  193. [formData appendPartWithFileURL:[NSURL URLWithString:value]  name:name fileName:fileName mimeType:mimeType error:nil];
  194. }
  195. }
  196. } error:nil];
  197. AFHTTPRequestOperation *operation = nil;
  198. operation = [operationManager HTTPRequestOperationWithRequest:request
  199. success:^(AFHTTPRequestOperation *operation, id responseObject) {
  200. FLOG(@"post responseObject:  %@",responseObject);
  201. if (complete) {
  202. complete(true,responseObject);
  203. }
  204. } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
  205. FLOG(@"post error :  %@",error);
  206. if (complete) {
  207. complete(false,nil);
  208. }
  209. }];
  210. [operation setUploadProgressBlock:^(NSUInteger bytesWritten, NSInteger totalBytesWritten, NSInteger totalBytesExpectedToWrite) {
  211. FLOG(@"upload process: %.2d%% (%ld/%ld)",100*totalBytesWritten/totalBytesExpectedToWrite,(long)totalBytesWritten,(long)totalBytesExpectedToWrite);
  212. if (process) {
  213. process(totalBytesWritten,totalBytesExpectedToWrite);
  214. }
  215. }];
  216. [operation start];
  217. return operation;
  218. }
  219. - (AFHTTPRequestOperation *)downloadFromUrl:(NSString *)url
  220. filePath:(NSString *)filePath
  221. complete:(void (^)(BOOL successed, NSDictionary *response))complete
  222. {
  223. return [self downloadFromUrl:url params:nil filePath:filePath process:nil complete:complete];
  224. }
  225. - (AFHTTPRequestOperation *)downloadFromUrl:(NSString *)url
  226. params:(NSDictionary *)params
  227. filePath:(NSString *)filePath
  228. process:(void (^)(NSInteger readBytes, NSInteger totalBytes))process
  229. complete:(void (^)(BOOL successed, NSDictionary *response))complete
  230. {
  231. params = [[HttpManager getRequestBodyWithParams:params] copy];
  232. AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer];
  233. NSMutableURLRequest *request = [serializer requestWithMethod:@"GET" URLString:url parameters:params error:nil];
  234. FLOG(@"get request url: %@",[request.URL.absoluteString decode]);
  235. AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
  236. operation.responseSerializer.acceptableContentTypes = nil;
  237. NSString *tmpPath = [filePath stringByAppendingString:@".tmp"];
  238. operation.outputStream=[[NSOutputStream alloc] initToFileAtPath:tmpPath append:NO];
  239. [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
  240. NSArray *mimeTypeArray = @[@"text/html", @"application/json"];
  241. NSError *moveError = nil;
  242. if ([mimeTypeArray containsObject:operation.response.MIMEType]) {
  243. //返回的是json格式数据
  244. responseObject = [NSData dataWithContentsOfFile:tmpPath];
  245. responseObject = [NSJSONSerialization JSONObjectWithData:responseObject options:2 error:nil];
  246. [[NSFileManager defaultManager] removeItemAtPath:tmpPath error:nil];
  247. FLOG(@"get responseObject:  %@",responseObject);
  248. }else{
  249. [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];
  250. [[NSFileManager defaultManager] moveItemAtPath:tmpPath toPath:filePath error:&moveError];
  251. }
  252. if (complete && !moveError) {
  253. complete(true,responseObject);
  254. }else{
  255. complete?complete(false,responseObject):nil;
  256. }
  257. } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
  258. FLOG(@"get error :  %@",error);
  259. [[NSFileManager defaultManager] removeItemAtPath:tmpPath error:nil];
  260. if (complete) {
  261. complete(false,nil);
  262. }
  263. }];
  264. [operation setDownloadProgressBlock:^(NSUInteger bytesRead, NSInteger totalBytesRead, NSInteger totalBytesExpectedToRead) {
  265. FLOG(@"download process: %.2d%% (%ld/%ld)",100*totalBytesRead/totalBytesExpectedToRead,(long)totalBytesRead,(long)totalBytesExpectedToRead);
  266. if (process) {
  267. process(totalBytesRead,totalBytesExpectedToRead);
  268. }
  269. }];
  270. [operation start];
  271. return operation;
  272. }
  273. + (NSMutableDictionary *)getRequestBodyWithParams:(NSDictionary *)params
  274. {
  275. NSMutableDictionary *requestBody = params?[params mutableCopy]:[[NSMutableDictionary alloc] init];
  276. for (NSString *key in [params allKeys]){
  277. id value = [params objectForKey:key];
  278. if ([value isKindOfClass:[NSDate class]]) {
  279. [requestBody setValue:@([value timeIntervalSince1970]*1000) forKey:key];
  280. }
  281. if ([value isKindOfClass:[NSDictionary class]] || [value isKindOfClass:[NSArray class]]) {
  282. [requestBody setValue:[value json] forKey:key];
  283. }
  284. }
  285. NSString *token = [[NSUserDefaults standardUserDefaults] objectForKey:@"token"];
  286. if (token){
  287. [requestBody setObject:token forKey:@"token"];
  288. }
  289. [requestBody setObject:@"ios" forKey:@"genus"];
  290. return requestBody;
  291. }
  292. + (NetworkStatus)networkStatus
  293. {
  294. Reachability *reachability = [Reachability reachabilityWithHostname:@"www.apple.com"];
  295. // NotReachable     - 没有网络连接
  296. // ReachableViaWWAN - 移动网络(2G、3G)
  297. // ReachableViaWiFi - WIFI网络
  298. return [reachability currentReachabilityStatus];
  299. }
  300. - (void)showMessageWithOperation:(AFHTTPRequestOperation *)operation method:(NSString *)method params:(NSDictionary *)params
  301. {
  302. NSString *urlAbsoluteString = [operation.request.URL.absoluteString decode];
  303. if ([[method uppercaseString] isEqualToString:@"GET"]) {
  304. FLOG(@"get request url:  %@  \n",urlAbsoluteString);
  305. }else{
  306. FLOG(@"%@ request url:  %@  \npost params:  %@\n",[method lowercaseString],urlAbsoluteString,params);
  307. }
  308. if (operation.error) {
  309. FLOG(@"%@ error :  %@",[method lowercaseString],operation.error);
  310. }else{
  311. FLOG(@"%@ responseObject:  %@",[method lowercaseString],operation.responseObject);
  312. }
  313. //    //只显示一部分url
  314. //    NSArray *ignordUrls = @[url_originalDataDownload,url_originalDataUpload,url_originalDataUploadFinished,url_getEarliestOriginalData,url_newVersion,
  315. //                            url_saveSyncFailInfo];
  316. //    for (NSString *ignordUrl in ignordUrls) {
  317. //        if ([urlAbsoluteString rangeOfString:ignordUrl].length) {
  318. //            return;
  319. //        }
  320. //    }
  321. //    //弹出网络提示
  322. //  if (!operation.error) {
  323. //      if ([operation.responseObject objectForKey:@"msg"] && [[operation.responseObject objectForKey:@"msg"] length]) {
  324. //          [KeyWindow showAlertMessage:[operation.responseObject objectForKey:@"msg"] callback:nil];
  325. //      }
  326. //  }
  327. //  else {
  328. //        if (operation.error.code == kCFURLErrorNotConnectedToInternet) {
  329. //            [KeyWindow showAlertMessage:@"您已断开网络连接" callback:nil];
  330. //        } else {
  331. //            [KeyWindow showAlertMessage:@"服务器忙,请稍后再试" callback:nil];
  332. //        }
  333. //  }
  334. }
  335. @end

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

//  ImageCache.h

  1. //
  2. //  ImageCache.h
  3. //  CoreDataUtil
  4. //
  5. //  Created by marujun on 14-1-18.
  6. //  Copyright (c) 2014年 jizhi. All rights reserved.
  7. //
  8. #import <UIKit/UIKit.h>
  9. #import <UIKit/UIImageView.h>
  10. #import <UIKit/UIButton.h>
  11. #import <objc/runtime.h>
  12. #define ADD_DYNAMIC_PROPERTY(PROPERTY_TYPE,PROPERTY_NAME,SETTER_NAME) \
  13. @dynamic PROPERTY_NAME ; \
  14. static char kProperty##PROPERTY_NAME; \
  15. - ( PROPERTY_TYPE ) PROPERTY_NAME{ \
  16. return ( PROPERTY_TYPE ) objc_getAssociatedObject(self, &(kProperty##PROPERTY_NAME ) ); \
  17. } \
  18. - (void) SETTER_NAME :( PROPERTY_TYPE ) PROPERTY_NAME{ \
  19. objc_setAssociatedObject(self, &kProperty##PROPERTY_NAME , PROPERTY_NAME , OBJC_ASSOCIATION_RETAIN); \
  20. } \
  21. @interface UIImage (ImageCache)
  22. @property(nonatomic, strong)NSString *lastCacheUrl;
  23. /* ********************----------*****************************
  24. 1、UIImage 的扩展方法,用于缓存图片;如果图片已下载则使用本地图片
  25. 2、下载完成之后会执行回调,并可查看下载进度
  26. ********************----------******************************/
  27. + (void)imageWithURL:(NSString *)url callback:(void(^)(UIImage *image))callback;
  28. + (void)imageWithURL:(NSString *)url
  29. process:(void (^)(NSInteger readBytes, NSInteger totalBytes))process
  30. callback:(void(^)(UIImage *image))callback;
  31. /*通过URL获取缓存图片在本地对应的路径*/
  32. + (NSString *)getImagePathWithURL:(NSString *)url;
  33. @end
  34. @interface UIImageView (ImageCache)
  35. @property(nonatomic, strong)NSString *lastCacheUrl;
  36. /*设置UIImageView的图片的URL,下载失败设置图片为空*/
  37. - (void)setImageURL:(NSString *)url;
  38. /*设置UIImageView的图片的URL,下载失败则使用默认图片设置*/
  39. - (void)setImageURL:(NSString *)url defaultImage:(UIImage *)defaultImage;
  40. /*设置UIImageView的图片的URL,下载完成之后先设置图片然后执行回调函数*/
  41. - (void)setImageURL:(NSString *)url callback:(void(^)(UIImage *image))callback;
  42. @end
  43. @interface UIButton (ImageCache)
  44. @property(nonatomic, strong)NSString *lastCacheUrl;
  45. /*设置按钮的图片的URL,下载失败设置图片为空*/
  46. - (void)setImageURL:(NSString *)url forState:(UIControlState)state;
  47. /*设置按钮的图片的URL,下载失败则使用默认图片设置*/
  48. - (void)setImageURL:(NSString *)url forState:(UIControlState)state defaultImage:(UIImage *)defaultImage;
  49. /*设置按钮的图片的URL,下载完成之后先设置图片然后执行回调函数*/
  50. - (void)setImageURL:(NSString *)url forState:(UIControlState)state callback:(void(^)(UIImage *image))callback;
  51. /*设置按钮的背景图片的URL,下载失败设置图片为空*/
  52. - (void)setBackgroundImageURL:(NSString *)url forState:(UIControlState)state;
  53. /*设置按钮的背景图片的URL,下载失败则使用默认图片设置*/
  54. - (void)setBackgroundImageURL:(NSString *)url forState:(UIControlState)state defaultImage:(UIImage *)defaultImage;
  55. /*设置按钮的背景图片的URL,下载完成之后先设置图片然后执行回调函数*/
  56. - (void)setBackgroundImageURL:(NSString *)url forState:(UIControlState)state callback:(void(^)(UIImage *image))callback;
  57. @end

//  ImageCache.m

  1. //
  2. //  ImageCache.m
  3. //  CoreDataUtil
  4. //
  5. //  Created by marujun on 14-1-18.
  6. //  Copyright (c) 2014年 jizhi. All rights reserved.
  7. //
  8. #import "ImageCache.h"
  9. #import "HttpManager.h"
  10. static NSMutableArray *downloadTaskArray_ImageCache;
  11. static BOOL isDownloading_ImageCache;
  12. @implementation UIImage (ImageCache)
  13. ADD_DYNAMIC_PROPERTY(NSString *,lastCacheUrl,setLastCacheUrl);
  14. + (void)imageWithURL:(NSString *)url callback:(void(^)(UIImage *image))callback
  15. {
  16. [self imageWithURL:url process:nil callback:callback];
  17. }
  18. + (void)imageWithURL:(NSString *)url
  19. process:(void (^)(NSInteger readBytes, NSInteger totalBytes))process
  20. callback:(void(^)(UIImage *image))callback
  21. {
  22. if (!downloadTaskArray_ImageCache) {
  23. downloadTaskArray_ImageCache = [[NSMutableArray alloc] init];
  24. }
  25. NSString *filePath = [self getImagePathWithURL:url];
  26. if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
  27. UIImage *lastImage = [UIImage imageWithContentsOfFile:filePath];
  28. lastImage.lastCacheUrl = url?url:@"";
  29. callback ? callback(lastImage) : nil;
  30. }else{
  31. NSMutableDictionary *task = [[NSMutableDictionary alloc] init];
  32. url?[task setObject:url forKey:@"url"]:nil;
  33. process?[task setObject:process forKey:@"process"]:nil;
  34. callback?[task setObject:callback forKey:@"callback"]:nil;
  35. [downloadTaskArray_ImageCache addObject:task];
  36. [self startDownload];
  37. }
  38. }
  39. + (void)startDownload
  40. {
  41. if (downloadTaskArray_ImageCache.count && !isDownloading_ImageCache) {
  42. NSDictionary *lastObj = [downloadTaskArray_ImageCache lastObject];
  43. [self downloadWithURL:lastObj[@"url"] process:lastObj[@"process"] callback:lastObj[@"callback"]];
  44. }
  45. }
  46. + (void)downloadWithURL:(NSString *)url
  47. process:(void (^)(NSInteger readBytes, NSInteger totalBytes))process
  48. callback:(void(^)(UIImage *image))callback
  49. {
  50. NSString *filePath = [self getImagePathWithURL:url];
  51. NSMutableDictionary *task = [[NSMutableDictionary alloc] init];
  52. url?[task setObject:url forKey:@"url"]:nil;
  53. process?[task setObject:process forKey:@"process"]:nil;
  54. callback?[task setObject:callback forKey:@"callback"]:nil;
  55. isDownloading_ImageCache = true;
  56. if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
  57. UIImage *lastImage = [UIImage imageWithContentsOfFile:filePath];
  58. lastImage.lastCacheUrl = url?url:@"";
  59. callback ? callback(lastImage) : nil;
  60. [downloadTaskArray_ImageCache removeObject:task];
  61. isDownloading_ImageCache = false;
  62. [self startDownload];
  63. }else{
  64. [[HttpManager defaultManager] downloadFromUrl:url
  65. params:nil
  66. filePath:filePath
  67. process:process
  68. complete:^(BOOL successed, NSDictionary *result) {
  69. if (callback) {
  70. if (successed && !result) {
  71. UIImage *lastImage = [UIImage imageWithContentsOfFile:filePath];
  72. lastImage.lastCacheUrl = url?url:@"";
  73. callback ? callback(lastImage) : nil;
  74. }else{
  75. callback(nil);
  76. }
  77. }
  78. [downloadTaskArray_ImageCache removeObject:task];
  79. isDownloading_ImageCache = false;
  80. [self startDownload];
  81. }];
  82. }
  83. }
  84. + (NSString *)getImagePathWithURL:(NSString *)url
  85. {
  86. //先创建个缓存文件夹
  87. NSString *directory = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Caches/imgcache"];
  88. NSFileManager *defaultManager = [NSFileManager defaultManager];
  89. if (![defaultManager fileExistsAtPath:directory]) {
  90. [defaultManager createDirectoryAtPath:directory withIntermediateDirectories:YES attributes:nil error:nil];
  91. }
  92. return [directory stringByAppendingPathComponent:[url md5]];
  93. }
  94. @end
  95. @implementation UIImageView (ImageCache)
  96. ADD_DYNAMIC_PROPERTY(NSString *,lastCacheUrl,setLastCacheUrl);
  97. - (void)setImageURL:(NSString *)url
  98. {
  99. [self setImageURL:url callback:nil];
  100. }
  101. - (void)setImageURL:(NSString *)url defaultImage:(UIImage *)defaultImage
  102. {
  103. defaultImage ? self.image=defaultImage : nil;
  104. self.lastCacheUrl = url;
  105. [UIImage imageWithURL:url callback:^(UIImage *image) {
  106. if ([image.lastCacheUrl isEqualToString:self.lastCacheUrl]) {
  107. image ? self.image=image : nil;
  108. }
  109. }];
  110. }
  111. - (void)setImageURL:(NSString *)url callback:(void(^)(UIImage *image))callback
  112. {
  113. self.lastCacheUrl = url;
  114. [UIImage imageWithURL:url callback:^(UIImage *image) {
  115. if ([image.lastCacheUrl isEqualToString:self.lastCacheUrl]) {
  116. image ? self.image=image : nil;
  117. }
  118. callback ? callback(image) : nil;
  119. }];
  120. }
  121. @end
  122. @implementation UIButton (ImageCache)
  123. ADD_DYNAMIC_PROPERTY(NSString *,lastCacheUrl,setLastCacheUrl);
  124. - (void)setImageURL:(NSString *)url forState:(UIControlState)state
  125. {
  126. [self setImageURL:url forState:state defaultImage:nil];
  127. }
  128. - (void)setImageURL:(NSString *)url forState:(UIControlState)state defaultImage:(UIImage *)defaultImage
  129. {
  130. defaultImage ? [self setImage:defaultImage forState:state] : nil;
  131. self.lastCacheUrl = url;
  132. [UIImage imageWithURL:url callback:^(UIImage *image) {
  133. if ([image.lastCacheUrl isEqualToString:self.lastCacheUrl]) {
  134. image ? [self setImage:image forState:state] : nil;
  135. }
  136. }];
  137. }
  138. - (void)setImageURL:(NSString *)url forState:(UIControlState)state callback:(void(^)(UIImage *image))callback
  139. {
  140. self.lastCacheUrl = url;
  141. [UIImage imageWithURL:url callback:^(UIImage *image) {
  142. if ([image.lastCacheUrl isEqualToString:self.lastCacheUrl]) {
  143. image ? [self setImage:image forState:state] : nil;
  144. }
  145. callback ? callback(image) : nil;
  146. }];
  147. }
  148. - (void)setBackgroundImageURL:(NSString *)url forState:(UIControlState)state
  149. {
  150. [self setBackgroundImageURL:url forState:state defaultImage:nil];
  151. }
  152. - (void)setBackgroundImageURL:(NSString *)url forState:(UIControlState)state defaultImage:(UIImage *)defaultImage
  153. {
  154. defaultImage ? [self setBackgroundImage:defaultImage forState:state] : nil;
  155. self.lastCacheUrl = url;
  156. [UIImage imageWithURL:url callback:^(UIImage *image) {
  157. if ([image.lastCacheUrl isEqualToString:self.lastCacheUrl]) {
  158. image ? [self setBackgroundImage:image forState:state] : nil;
  159. }
  160. }];
  161. }
  162. - (void)setBackgroundImageURL:(NSString *)url forState:(UIControlState)state callback:(void(^)(UIImage *image))callback
  163. {
  164. self.lastCacheUrl = url;
  165. [UIImage imageWithURL:url callback:^(UIImage *image) {
  166. if ([image.lastCacheUrl isEqualToString:self.lastCacheUrl]) {
  167. image ? [self setBackgroundImage:image forState:state] : nil;
  168. }
  169. callback ? callback(image) : nil;
  170. }];
  171. }
  172. @end
  1. /*  使用示例 */
  2. NSString *url = @"http://b.hiphotos.baidu.com/image/w%3D2048/sign=4c2a6e019058d109c4e3aeb2e560cdbf/b812c8fcc3cec3fd6d7daa0ad488d43f87942709.jpg";
  3. //缓存图片
  4. //    [UIImage imageWithURL:url process:^(NSInteger readBytes, NSInteger totalBytes) {
  5. //        NSLog(@"下载进度 : %.0f%%",100*readBytes/totalBytes);
  6. //    } callback:^(UIImage *image) {
  7. //        NSLog(@"图片下载完成!");
  8. //    }];
  9. //设置UIImageView的图片,下载失败则使用默认图片
  10. UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.view.bounds];
  11. [imageView setImageURL:url defaultImage:[UIImage imageNamed:@"default.png"]];
  12. imageView.contentMode = UIViewContentModeScaleAspectFit;
  13. [self.view addSubview:imageView];
  14. //设置UIButton的图片,下载失败则使用默认图片
  15. UIButton *button = [[UIButton alloc] initWithFrame:self.view.bounds];
  16. [button setImageURL:url forState:UIControlStateNormal defaultImage:[UIImage imageNamed:@"default.png"]];
  17. [self.view addSubview:button];

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