SDWebImage中用到的运行时

1、SDWebImage中用到的运行时机制。

导入头文件

#import

@implementation UIImageView (WebCache)

const char *previousURLStringKey = "previousURLStringKey";

- (NSString *)previousURLString

{

    return objc_getAssociatedObject(self, previousURLStringKey);

}

  // 这里要用到的是运行时机制,分类不能增加属性,只能增加方法

    // 这个方法是动态的为某一个类添加属性

    // 指的将要绑定的对象

    // 键名

    // 保存的是哪个值

    //

    

    objc_setAssociatedObject(self, previousURLStringKey, previousURLString, OBJC_ASSOCIATION_COPY_NONATOMIC);

    

}

- (void)setImageWithURLString:(NSString *)URLString

{

    

    DHOperationManager *manager = [DHOperationManager sharedManager];

    if ([URLString isEqualToString:self.previousURLString] == NO) {

        // 当前的URLString不等于previousURLString

        // 取消上一个的下载任务

        [manager cancelOperationWith:self.previousURLString];

    }

    

    

    // 根据当前的URLString去下载

    [manager downloadWithURLString:URLString andFinishedBlock:^(UIImage *image) {

        

        self.image = image;

        NSLog(@"%@----",[NSThread currentThread]);

    }];

    

    self.previousURLString = URLString;

}

2、自定义操作

// 1/先调start,后调main

- (void)start

{

    NSLog(@"%s",__func__);

    [super start];

}

- (void)main

{

    NSLog(@"%s",__func__);

   

    @autoreleasepool {

      

        // 在这里不断监测

        if (self.isCancelled) {

            return;

        }

        

        // 这个方法默认已经帮我们创建好了子线程,不需要再开启新的线程

        NSURL *url = [NSURL URLWithString:self.innerURLString];

        

        // 在这里不断监测

        if (self.isCancelled) {

            return;

        }

        

        [NSThread sleepForTimeInterval:3.0];

        

        NSData *data = [NSData dataWithContentsOfURL:url];

        // 在这里不断监测

        if (self.isCancelled) {

            return;

        }

        

        if (data) {

            // 将二进制数据存储到沙盒中

            [data writeToFile:[NSString fileNameWithURLString:self.innerURLString] atomically:YES];

        }

        

        

        UIImage *image = [UIImage imageWithData:data];

        // 在这里不断监测

        if (self.isCancelled) {

            return;

        }

        

        // 调用block传递参数,这个block已经放在主线程上执行,

        [[NSOperationQueue mainQueue] addOperationWithBlock:^{

            // 在这里不断监测

            if (self.isCancelled) {

                return;

            }

            self.innerFinishedBlock(image);

        }];

        

        //NSLog(@"%@",[NSThread currentThread]);

    }

}

3、管理者

// 操作缓存

- (NSMutableDictionary *)operationCache

{

    if (_operationCache == nil) {

        _operationCache = [NSMutableDictionary dictionary];

    }

    return _operationCache;

}

// 内存缓存

- (NSCache *)imageCache

{

    if (_imageCache == nil) {

        _imageCache = [[NSCache alloc] init];

    }

    return _imageCache;

}

// 并发队列的懒加载

- (NSOperationQueue *)concurrentQueue

{

    if (_concurrentQueue == nil) {

        _concurrentQueue = [[NSOperationQueue alloc] init];

    }

    return _concurrentQueue;

}

static DHOperationManager *_instance;

+ (instancetype)sharedManager

{

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        _instance = [[self alloc] init];

    });

    return _instance;

}

- (instancetype)init

{

    if (self = [super init]) {

    

        // 添加观察者

        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(cleanImageCache) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];

    }

    return self;

}

// 移除监听

- (void)dealloc

{

    [[NSNotificationCenter defaultCenter] removeObserver:self];

}

- (void)downloadWithURLString:(NSString *)URLString andFinishedBlock:(FinishedBlock)finishedBlock

{

    // 1、先从内存中取

    UIImage *ramImage = [self.imageCache objectForKey:URLString];

    if (ramImage) {

        

        NSLog(@"ram");

        finishedBlock(ramImage);

        

        return;

    }

    

    // 2、从沙盒中取

    NSData *data = [NSData dataWithContentsOfFile:[NSString fileNameWithURLString:URLString]];

    if (data) {

        

        NSLog(@"local");

        // 将二进制数据转化成image

        UIImage *localImage = [UIImage imageWithData:data];

        

        // 将取出来的存放到内存zhong

        [self.imageCache setObject:localImage forKey:URLString];

        

        finishedBlock(localImage);

        

        return;

    }

    

    // 3、判断该操作是否已经存在,防止用户反复点击

    if ([self.operationCache objectForKey:URLString]) {

        NSLog(@"loading");

        return;

    }

    

    

    // 4、去下载

    DHDownloadImageOperation *operation = [DHDownloadImageOperation downloadImageOperationWithURLString:URLString andFinishedBlock:^(UIImage *image) {

        

        // 1、将图片缓存写入内存中

        [self.imageCache setObject:image forKey:URLString];

        

        // 将下载好的操作移出字典中

        [self.operationCache removeObjectForKey:URLString];

        

        NSLog(@"download");

        

        // 2、调用传入的block

        finishedBlock(image);

    }];

    

    // 5、将操作放入到队列中

    [self.concurrentQueue addOperation:operation];

    // 将操作放入字典中

    [self.operationCache setObject:operation forKey:URLString];

}

- (void)cancelOperationWith:(NSString *)URLString

{

    // 根据URLString在缓存中取出操作

    DHDownloadImageOperation *operation = [self.operationCache objectForKey:URLString];

    

    // 当URLString改变过快,此时可能操作字典中还没有将任务添加到字典

    // 所以先判断当前的操作在不在字典中

    if (operation == nil) {

        return;

    }

    

    //操作字典中存放的是正在执行的操作

    // 取消当前操作

    // cancel只是给当前任务一个标签并不会立即停止该任务,要在任务执行的时候根据这个信号去判断是继续执行还是立即返回

    [operation cancel];

    

    // 从当前操作字典中移除

    [self.operationCache removeObjectForKey:URLString];

}

- (void)cleanImageCache

{

    // 清除缓存

    [self.imageCache removeAllObjects];

}


你可能感兴趣的:(iOS,SDWebImage,运行时)