// NSString 的分類 g更好的對沙盒操做 ............ ..................h #import <Foundation/Foundation.h> @interface NSString (sandBox) //獲取cache路徑 - (instancetype)appdentCache; //獲取Document路徑 - (instancetype)appdentDocument; //獲取Tmp路徑 - (instancetype)appdentTmp; @end ............ ..................m #import "NSString+sandBox.h" @implementation NSString (sandBox) - (instancetype)appdentCache { return [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:[self lastPathComponent]]; } //獲取Document路徑 - (instancetype)appdentDocument { return [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:[self lastPathComponent]]; } //獲取Tmp路徑 - (instancetype)appdentTmp { return [NSTemporaryDirectory() stringByAppendingPathComponent:[self lastPathComponent]]; } @end
// UIImageView 的分類 ............................h #import <UIKit/UIKit.h> @interface UIImageView (WebCache) - (void)setimageWithUrlstr:(NSString *)urlstr; @end ............................m #define MYKEY "BF" #import "UIImageView+WebCache.h" #import "MydownloadOperationManager.h" #import <objc/runtime.h> @interface UIImageView () //獲取當前的圖片地址 @property (nonatomic, copy) NSString *currentStr; @end @implementation UIImageView (WebCache) -(void)setCurrentStr:(NSString *)currentStr { objc_setAssociatedObject(self, MYKEY, currentStr, OBJC_ASSOCIATION_COPY_NONATOMIC); } -(NSString *)currentStr { return objc_getAssociatedObject(self,MYKEY); } - (void)setimageWithUrlstr:(NSString *)urlstr { //判斷此次點擊屏幕獲取的圖片地址和上次記錄下來的圖片地址進行比較,若是不相同,取消上次的操做 if (![urlstr isEqualToString:self.currentStr]) { // //取消上次操做 [[MydownloadOperationManager sharedDownloadOperationManager]cancelOperationWithUrlstr:self.currentStr]; } //記錄當前的圖片地址 self.currentStr = urlstr; //圖片下載-下載操做管理類 [[MydownloadOperationManager sharedDownloadOperationManager]downloadWithUrlstr:urlstr finishedBlock:^(UIImage *img) { self.image = img; }]; } @end
// 自定義的NSOperation的類 ------------------------------- .h // Created by 朱保鋒 on 16/3/8. // Copyright © 2016年 朱保鋒. All rights reserved. // #import <Foundation/Foundation.h> #import <UIKit/UIKit.h> @interface BFOperation : NSOperation // 從外界傳過來的字符串 @property (nonatomic,copy)NSString *urlstr; // 用來進行刷新操做的block @property (nonatomic,copy)void (^finishedBlock)(UIImage *); // 類方法的實現 + (instancetype)operationWithUrlstr:(NSString *)urlstr and :(void (^)(UIImage *img)) finsihedblock; @end ----------------------------------------.m // Created by 朱保鋒 on 16/3/8. // Copyright © 2016年 朱保鋒. All rights reserved. // #import "BFOperation.h" #import "NSString+sandBox.h" @implementation BFOperation - (void)main{ @autoreleasepool { NSLog(@"%@", [NSThread currentThread]); // 從網上下載圖片 NSURL *url = [NSURL URLWithString:self.urlstr]; NSData *data = [NSData dataWithContentsOfURL:url]; UIImage *img = [UIImage imageWithData:data]; // 存入沙盒 if (img) { [data writeToFile:[self.urlstr appdentCache] atomically:YES]; } // 判斷取消狀態 看是否中止該操做 if (self.isCancelled) { return; } // 主線程刷新 [[NSOperationQueue mainQueue]addOperationWithBlock:^{ // 在這個地方去調用block self.finishedBlock(img); }]; } } // 類方法的實現 + (instancetype)operationWithUrlstr:(NSString *)urlstr and :(void (^)(UIImage *img)) finsihedblock{ BFOperation *op = [BFOperation new]; op.urlstr = urlstr; op.finishedBlock = finsihedblock; //這裏的操做能明白嗎 return op; } @end
// 定義管理操做類的單例 體現出了封裝層次的思想 ......................................h // Created by 朱保鋒 on 16/3/8. // Copyright © 2016年 朱保鋒. All rights reserved. // #import <Foundation/Foundation.h> #import <UIKit/UIKit.h> @interface BFOperationManger : NSObject // 是個單例 用它去進行管理 + (instancetype)sharedOperationManger; // 經過字符串 進行操做 - (void)downloadImageWithUrlstr :(NSString *)urlstr and :(void (^)(UIImage * img))finsihedblock; @end .......................................m // Created by 朱保鋒 on 16/3/8. // Copyright © 2016年 朱保鋒. All rights reserved. // #import "BFOperationManger.h" #import "BFOperation.h" #import "NSString+sandBox.h" @interface BFOperationManger () @property (nonatomic,strong)NSOperationQueue *queue; // 操做緩存池 @property (nonatomic,strong)NSMutableDictionary *opCache; // 保存上一個圖片的地址,用來進行判斷 @property (nonatomic,copy)NSString *currentStr; // 建立一個圖片緩存池 @property (nonatomic,strong)NSMutableDictionary *imgCache; @end @implementation BFOperationManger - (NSMutableDictionary *)imgCache{ if (_imgCache == nil) { _imgCache = [NSMutableDictionary dictionaryWithCapacity:10]; } return _imgCache; } - (NSMutableDictionary *)opCache{ if ( _opCache == nil) { _opCache = [NSMutableDictionary dictionaryWithCapacity:10]; } return _opCache; } - (NSOperationQueue *)queue{ if (_queue == nil) { _queue = [NSOperationQueue new]; } return _queue; } + (instancetype)sharedOperationManger{ static BFOperationManger *opM = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ opM = [BFOperationManger new]; }); return opM; } - (void)downloadImageWithUrlstr:(NSString *)urlstr and:(void (^)(UIImage *))finsihedblock{ if ([self checkImageExist:urlstr]) { finsihedblock(self.imgCache[urlstr]); NSLog(@"這個線程是:%@",[NSThread currentThread]); // 如果緩存或者內存中有值 就不用去調用,本身首先,沒有產生新的線程 return; } [self cancleOp:urlstr]; self.currentStr = urlstr; BFOperation *op = [BFOperation operationWithUrlstr:urlstr and:^(UIImage *img) { finsihedblock(img); // 在這個地方就要把圖片添加進去 // NSLog(@"asdasdda%@",[NSThread currentThread]); self.imgCache[urlstr] = img; }]; [self.queue addOperation:op]; // 將操做添加到緩存池中 self.opCache[urlstr] = op; } // 把從網絡下載的時候 把這個操做取消 - (void)cancleOp:(NSString *)urlstr{ if (self.currentStr == nil) { return; } if (![self.currentStr isEqualToString:urlstr]) { // 取消 [self.opCache[self.currentStr] cancel]; // 移除 [self.opCache removeObjectForKey:self.currentStr]; } } // 方法 判斷內存 沙盒中是否用這個圖片 - (BOOL)checkImageExist:(NSString *)urlstr{ // 內存 if (self.imgCache[urlstr]) { NSLog(@"從內存中加載"); return YES; } // 沙盒 NSString *path = [urlstr appdentCache]; NSData *data = [NSData dataWithContentsOfFile:path]; UIImage *img = [UIImage imageWithData:data]; if (img) { NSLog(@"從沙盒裏面讀取"); self.imgCache[urlstr] = img; return YES; } return NO; } @end