「翻译」运行时之关联对象

头文件html

#import <objc/runtime.h>

Objective-C 开发者习惯于警戒运行时的东西,理由是运行时改变了运行在它上面代码的实际结构。ios

另外一方面,<objc/runtime.h> 的功能就是为应用或框架增长更强大的新特性,是其余的方式没法git

实现的。同时它也可能破坏原来代码的逻辑结构,一切与之可能进行的交互,都将有可怕的反作用github

给咱们带来极大的惶恐,所以,咱们称之为浮士德,也是NSHipster读者常常被所要求的科目之一:缓存

关联的对象关联的对象或关联的引用,他们本来是Objective-C的2.0运行时的新特性,在OS Xapp

雪豹中介绍(可在iOS 4的)的功能。运行时键值许对象为任意值,这个条目是在框架

<objc/ runtime.h>声明的如下三个C函数异步

  • objc_setAssociatedObject
  • objc_getAssociatedObject
  • objc_removeAssociatedObjects

为何会这样有用吗?它容许开发人员在分类中自定义属性,拓展的类,弥补Objective-C的这个缺陷ide

 
 
NSObject+AssociatedObject.h

@interface
NSObject (AssociatedObject) @property (nonatomic, strong) id associatedObject; @end
NSObject+AssociatedObject.m

@implementation NSObject (AssociatedObject)
@dynamic associatedObject;

- (void)setAssociatedObject:(id)object {
     objc_setAssociatedObject(self, @selector(associatedObject), object, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (id)associatedObject {
    return objc_getAssociatedObject(self, @selector(associatedObject));
}

人们一般的建议是使用静态字符,或者更好的是指针。这基本上保证一个任意的值是固定的、惟一的,函数

并且仅限于getter和setter方法​​中使用

static char kAssociatedObjectKey;

objc_getAssociatedObject(self, &kAssociatedObjectKey);

然而一个更简单的解决方案存在:只使用一个SEL

 

关联对象的行为

值能够根据由枚举类型objc_AssociationPolicy定义的行为相关联的物体上

 
Behavior @property Equivalent Description
OBJC_ASSOCIATION_ASSIGN @property (assign) or @property (unsafe_unretained) Specifies a weak reference to the associated object.
OBJC_ASSOCIATION_RETAIN_NONATOMIC @property (nonatomic, strong) Specifies a strong reference to the associated object, and that the association is not made atomically.
OBJC_ASSOCIATION_COPY_NONATOMIC @property (nonatomic, copy) Specifies that the associated object is copied, and that the association is not made atomically.
OBJC_ASSOCIATION_RETAIN @property (atomic, strong) Specifies a strong reference to the associated object, and that the association is made atomically.
OBJC_ASSOCIATION_COPY @property (atomic, copy) Specifies that the associated object is copied, and that the association is made atomically.
 
 
弱引用与OBJC_ASSOCIATION_ASSIGN是有区别的,弱引用和unsafe_unretained行为相似,这
意味着应该谨慎地实现访问弱关联的对象。 根据在WWDC2011会话322(〜36:00)的Deallocation
Timeline 描述,相关联对象的删除迟于该对象的生命周期,在object_dispose(),它是由NSObject
的-dealloc调用。

移除值

有人可能控制不住地各类诱惑,在他们某些关联的对象时调用objc_removeAssociatedObjects()。

可是,如文档中描述的,你基本没有将有机会亲自调用它: 此函数的主要目的是能够很容易将对象返回

“原始状态”,你不该该使用这个函数从对象通常移除关联,由于它也消除了其余对象可能已添加到该

对象关联。一般状况下,你应该使用objc_setAssociatedObject 设置nil,以清除关联

模式

  • 添加私有变量,以方便实现细节。当延伸的内置类的行为时,记录附加状态多是必要的。这是能够当作教科书的关联对象的例子。例如,AFNetworking在UIImageView分类中使用关联对象来存储请求操做的对象,用于异步获取一个远程、特定的URL上的图像。
  • 添加公共属性来配置类的行为。有时,用属性可使分类更加灵活,比方法参数也更有意义。在这种状况下,一个面向大众的属性是使用关联的对象是能够接受的。回到AFNetworking例子中,它的UIImageView分类的imageResponseSerializer,容许图像视图有选择地应用过滤 器,另外一方面也能够在设置和缓存到磁盘前更改远程图像的渲染。
  • 建立一个KVO的关联观察者。当在分类的实现中使用KVO时,一般推荐使用自定义的关联对象能够做为一个观察者,而不是观察的对象自己。

反模式

  • 不须要值时存储关联的对象。一个常见的视图模式是建立填充基于模型对象或复合值的字段和属性的便捷方法。若是该值之后不须要回调,就不与该对象相关联,这是能够接受的,也是合理的。
  • 当 值能够被推断出来时存储关联的对象。例如,一我的也许会存储一个自定义辅助视图的包含的UITableViewCell的引用,用于实现代码如 下:tableView:accessoryButtonTappedForRowWithIndexPath:,这时候能够经过调用 cellForRowAtIndexPath: 恢复。
  • 在以下的状况使用关联的对象
    • 继承比组合更合理时的子类
    • 添加交互事件响应的 "目标-动做"
    • 目标-动做不起做用时的 手势识别
    • 行为能够委托给另外一个对象的代理。
    • 松耦合方式的跨系统通讯事件的通知、通知中心

相关联的对象应被看做是不得已的方法,而不是寻找问题的解决方案(说真的,类自己真的不该该在工具链的顶端开始)。 如同任何聪明的把戏,骇客攻击,或解决方法,通常都会积极寻求应用的场合,尤为是了解以后,这是人的一种天然的倾向 。尽你所能地理解和欣赏时,这是正确的解决方案,保存本身被轻蔑地问:“为何要以神的名义”,而后你决定去解决。

 

相关代码:

https://github.com/skyming/BlockUI/tree/master/BlockUI

相关文章
相关标签/搜索