SDWebImage源码阅读(十五)UIView+WebCacheOperation

  这个分类主要用来对 UIView 的图像下载操作添加、取消和移除。

 .h

1  *  Set the image load operation (storage in a UIView based dictionary)
2  *
3  *  @param operation the operation
4  *  @param key       key for storing the operation
5  */
6 - (void)sd_setImageLoadOperation:(nullable id)operation forKey:(nullable NSString *)key;

  设置图像加载操作。

1 /**
2  *  Cancel all operations for the current UIView and key
3  *
4  *  @param key key for identifying the operations
5  */
6 - (void)sd_cancelImageLoadOperationWithKey:(nullable NSString *)key;

  根据 key 取消 UIView 的所有当前操作。

1 /**
2  *  Just remove the operations corresponding to the current UIView and key without cancelling them
3  *
4  *  @param key key for identifying the operations
5  */
6 - (void)sd_removeImageLoadOperationWithKey:(nullable NSString *)key;

  仅仅根据 key 移除对应的当前 UIView 的操作,并没有取消它们。

 .m

1 static char loadOperationKey;
2 
3 typedef NSMutableDictionary<NSString *, id> SDOperationsDictionary;

  定义一个静态 char loadOperationKey,主要用于下面关联的关键字使用。

  定义一个 key 是字符串 value 是id 的可变字典类型。

1 - (SDOperationsDictionary *)operationDictionary {
2     SDOperationsDictionary *operations = objc_getAssociatedObject(self, &loadOperationKey);
3     if (operations) {
4         return operations;
5     }
6     operations = [NSMutableDictionary dictionary];
7     objc_setAssociatedObject(self, &loadOperationKey, operations, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
8     return operations;
9 }

  给 UIView 关联一个 operationDictionary 对象(类似添加一个属性)。

 objc_getAssociatedObject

 1 /** 
 2  * Returns the value associated with a given object for a given key.
 3  * 
 4  * @param object The source object for the association.
 5  * @param key The key for the association.
 6  * 
 7  * @return The value associated with the key \e key for \e object.
 8  * 
 9  * @see objc_setAssociatedObject
10  */
11 OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key)
12     OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0);

  使用给定的关联键和源对象返回被关联对象的值。

 objc_setAssociatedObject

 1 /** 
 2  * Sets an associated value for a given object using a given key and association policy.
 3  * 
 4  * @param object The source object for the association.
 5  * @param key The key for the association.
 6  * @param value The value to associate with the key key for object. Pass nil to clear an existing association.
 7  * @param policy The policy for the association. For possible values, see “Associative Object Behaviors.”
 8  * 
 9  * @see objc_setAssociatedObject
10  * @see objc_removeAssociatedObjects
11  */
12 OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
13     OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0);

  使用给定的关联键和关联策略和关联对象的值设置源对象的关联值。

 objc_removeAssociatedObjects

 1 /** 
 2  * Removes all associations for a given object.
 3  * 
 4  * @param object An object that maintains associated objects.
 5  * 
 6  * @note The main purpose of this function is to make it easy to return an object 
 7  *  to a "pristine state”. You should not use this function for general removal of
 8  *  associations from objects, since it also removes associations that other clients
 9  *  may have added to the object. Typically you should use \c objc_setAssociatedObject 
10  *  with a nil value to clear an association.
11  * 
12  * @see objc_setAssociatedObject
13  * @see objc_getAssociatedObject
14  */
15 OBJC_EXPORT void objc_removeAssociatedObjects(id object)
16     OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0);

  删除源对象的所有关联。  

 objc_AssociationPolicy

 1 /**
 2  * Policies related to associative references.
 3  * These are options to objc_setAssociatedObject()
 4  */
 5 typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
 6     OBJC_ASSOCIATION_ASSIGN = 0,           /**< Specifies a weak reference to the associated object. */
 7     OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, /**< Specifies a strong reference to the associated object. 
 8                                             *   The association is not made atomically. */
 9     OBJC_ASSOCIATION_COPY_NONATOMIC = 3,   /**< Specifies that the associated object is copied. 
10                                             *   The association is not made atomically. */
11     OBJC_ASSOCIATION_RETAIN = 01401,       /**< Specifies a strong reference to the associated object.
12                                             *   The association is made atomically. */
13     OBJC_ASSOCIATION_COPY = 01403          /**< Specifies that the associated object is copied.
14                                             *   The association is made atomically. */
15 };

  与关联引用相关的策略。

 关联

  关联是把两个对象关联起来,使得其中一个对象作为另一个对象的一部分。

 在类的定义之外为类增加额外的存储空间:

  使用关联,可以不用修改类的定义而为其对象增加存储空间。这在无法访问到类的源码的时候(主要是系统的类)或者是考虑到二进制兼容性的时候非常有用。

  关联是基于关键字的,因此可以为任何对象增加任意多的关联,每个使用不同的关键字即可。关联是可以保证被关联的对象在关联对象的整个生命周期都是可用的(在 ARC 下也不会导致资源不可回收)。

 创建关联

  创建关联要使用 Objective-C 的运行时函数: objc_SetAssociatedObject 来把一个对象与另外一个对象进行关联,该函数使用了 4 个参数: 源对象、关键字(静态变量)、关联对象、关联策略。

  关键字是一个 void 类型的指针,每一个关联的关键字必须是唯一的,通常都是会采用静态变量来作为关键字。

  关联策略表明了相关的对象是通过赋值、保留引用还是复制的方式进行关联的,还有这种关联是原子的还是非原子的。

  关联策略和声明属性是很类似的,关联策略是通过使用预先定义好的常量来表示的。

 获取相关联的对象 

  获取相关联的对象即使用 Objective-C 函数 objc_getAssociatedObject。

 断开关联

  断开关联也是使用 objc_setAssociatedObject 函数,关联的关键字不变,关联的对象传入 nil 即可。

  使用 objc_removeAssociatedObjects 可以断开所有的关联,通常情况下不使用这个函数,它会断开所有的关联,只有在需要把对象恢复到原状态的时候才会使用这个函数。  

 1 - (void)sd_cancelImageLoadOperationWithKey:(nullable NSString *)key {
 2     // Cancel in progress downloader from queue
 3     SDOperationsDictionary *operationDictionary = [self operationDictionary];
 4     id operations = operationDictionary[key];
 5     if (operations) {
 6         if ([operations isKindOfClass:[NSArray class]]) {
 7             for (id <SDWebImageOperation> operation in operations) {
 8                 if (operation) {
 9                     [operation cancel];
10                 }
11             }
12         } else if ([operations conformsToProtocol:@protocol(SDWebImageOperation)]){
13             [(id<SDWebImageOperation>) operations cancel];
14         }
15         [operationDictionary removeObjectForKey:key];
16     }
17 }

  取消正在进行的下载队列,取消当前的所有操作。

  获取当前 UIView 对象使用关键字 loadOperationKey 所关联的对象 operationDictionary(存放下载操作的一个字典)。

  通过 key 获得该字典对应的 value 值 operations。

  如果这个 operations 存在(就是该 UIView 已经被添加过下载操作)且是一个数组,则遍历该数组对所有下载操作执行 cancel。

  如果这个 operations 不是数组,是一个 遵守 SDWebImageOperation 协议对象,则直接对它执行 cancel 操作。  

  移除关联对象 operationDictionary 里面 key 的 value 值。

1 - (void)sd_setImageLoadOperation:(nullable id)operation forKey:(nullable NSString *)key {
2     if (key) {
3         [self sd_cancelImageLoadOperationWithKey:key];
4         if (operation) {
5             SDOperationsDictionary *operationDictionary = [self operationDictionary];
6             operationDictionary[key] = operation;
7         }
8     }
9 }

  首先取消所有操作,把 operation 添加进 UIView 的关联对象内部。

1 - (void)sd_removeImageLoadOperationWithKey:(nullable NSString *)key {
2     if (key) {
3         SDOperationsDictionary *operationDictionary = [self operationDictionary];
4         [operationDictionary removeObjectForKey:key];
5     }
6 }

  移除当前 UIView 关联对象内部给定 key 下的操作,并没有对它们做取消操作。

参考链接:http://blog.csdn.net/onlyou930/article/details/9299169

 END

posted @ 2017-06-10 19:21  鳄鱼不怕牙医不怕  阅读(451)  评论(0编辑  收藏  举报