仿写SDWebImage中的一个网络加载图片的框架


// 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
原文地址:https://www.cnblogs.com/zhubaofeng/p/5374743.html