美文网首页
SDWebImage (5.1.0)UIView+WebCach

SDWebImage (5.1.0)UIView+WebCach

作者: charlotte2018 | 来源:发表于2019-09-19 14:15 被阅读0次
    #import "UIView+WebCacheOperation.h"
    #import "objc/runtime.h"
    
    static char loadOperationKey;
    
    // key is strong, value is weak because operation instance is retained by SDWebImageManager's runningOperations property
    // we should use lock to keep thread-safe because these method may not be acessed from main queue
    typedef NSMapTable<NSString *, id<SDWebImageOperation>> SDOperationsDictionary;
    
    @implementation UIView (WebCacheOperation)
    
    //获取任务字典NSMapTable,将NSMapTable关联对象到UIView
    - (SDOperationsDictionary *)sd_operationDictionary {
        @synchronized(self) {
            //如果取到operations就返回否则就创建,保证线程安全
            SDOperationsDictionary *operations = objc_getAssociatedObject(self, &loadOperationKey);
            if (operations) {
                return operations;
            }
            //https://www.jianshu.com/p/cf4e15b26f64
            //NSHashTable与NSMapTable
            //用NSMapTable保存operation,NSMapTable可以设置value为弱引用,key为强引用
            operations = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsStrongMemory valueOptions:NSPointerFunctionsWeakMemory capacity:0];
            objc_setAssociatedObject(self, &loadOperationKey, operations, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
            return operations;
        }
    }
    
    //通过key去拿operation
    - (nullable id<SDWebImageOperation>)sd_imageLoadOperationForKey:(nullable NSString *)key  {
        id<SDWebImageOperation> operation;
        if (key) {
            SDOperationsDictionary *operationDictionary = [self sd_operationDictionary];
            @synchronized (self) {
                operation = [operationDictionary objectForKey:key];
            }
        }
        return operation;
    }
    
    //设置key和value
    - (void)sd_setImageLoadOperation:(nullable id<SDWebImageOperation>)operation forKey:(nullable NSString *)key {
        if (key) {
            //先把之前的key对应的operation给删除了
            [self sd_cancelImageLoadOperationWithKey:key];
            //然后添加新的operation
            if (operation) {
                SDOperationsDictionary *operationDictionary = [self sd_operationDictionary];
                @synchronized (self) {
                    [operationDictionary setObject:operation forKey:key];
                }
            }
        }
    }
    
    //通过key把operation给取出来,然后调用cancel方法,取消下载
    - (void)sd_cancelImageLoadOperationWithKey:(nullable NSString *)key {
        if (key) {
            // Cancel in progress downloader from queue
            SDOperationsDictionary *operationDictionary = [self sd_operationDictionary];
            id<SDWebImageOperation> operation;
            
            @synchronized (self) {
                operation = [operationDictionary objectForKey:key];
            }
            if (operation) {
                if ([operation conformsToProtocol:@protocol(SDWebImageOperation)]) {
                    [operation cancel];
                }
                @synchronized (self) {
                    [operationDictionary removeObjectForKey:key];
                }
            }
        }
    }
    
    - (void)sd_removeImageLoadOperationWithKey:(nullable NSString *)key {
        if (key) {
            SDOperationsDictionary *operationDictionary = [self sd_operationDictionary];
            @synchronized (self) {
                [operationDictionary removeObjectForKey:key];
            }
        }
    }
    
    @end
    
    

    sd给每个UIView都绑定了一个NSMapTable用于存放当前的下载任务,这就解决了tableview在滑动的时候当cell复用时,image不会错位的问题,这个分类的作用就是解决错位的问题的,当我们给一个imageview下载图片时候,首先去NSMapTable里把当前正在执行的operation给cancel掉然后从NSMapTable移除,然后把新的任务加入到NSMapTable中,这是面试经常被问到的一个考点。

    https://sdwebimage.github.io/Categories/UIView(WebCacheOperation).html

    然后我们研究下这个NSMapTable,sd为什么不用NSMutableDictionary呢,说明NSMapTable和NSMutableDictionary是有区别的。

    key is strong, value is weak because operation instance is retained by SDWebImageManager's runningOperations property we should use lock to keep thread-safe because these method may not be acessed from main queue
    typedef NSMapTable<NSString *, id<SDWebImageOperation>> SDOperationsDictionary;
    

    / key很强,值很弱,因为SDWebImageManager的runningOperations属性保留了操作实例
    所以NSMapTable保存的value是弱引用的,当任务完成后自动会从NSMapTable中移除

    NSHashTable和NSMapTable相关文章

    https://www.jianshu.com/p/39b57ecc99fe
    https://objccn.io/issue-7-1/

    相关文章

      网友评论

          本文标题:SDWebImage (5.1.0)UIView+WebCach

          本文链接:https://www.haomeiwen.com/subject/omcgectx.html