曾静的博客

但行好事,莫问前程.

嗨,我是曾静 (@devzeng),目前暂居深圳。


这是我用来记录平日学习笔记的地方,欢迎您的访问.

Objective-C中的Associated Objects

Associated Objects(关联对象)或者叫做关联引用(Associated References),是作为Objective-C 2.0运行时功能被引入到Mac OS 10.6 Snow Leopard(及iOS4)系统。与它相关在<objc/rumtime.h>中有3个C函数,他们可以让对象在运行时关联任何值:

(1)用给定的key和policy来为指定对象(object)设置关联对象值(value)

void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)

(2)根据给定的key从指定对象(object)中获取相对应的关联对象值

id objc_getAssociatedObject(id object, const void *key)

(3)移除指定对象的全部关联对象

void objc_removeAssociatedObjects(id object)

开发者可以通过上面的几个函数在分类中给已存在的类中添加自定义的属性。

关联对象的特性

#import <objc/runtime.h>中关于objc_AssociationPolicy的定义如下:

enum {
    OBJC_ASSOCIATION_ASSIGN = 0,
    OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1,
    OBJC_ASSOCIATION_COPY_NONATOMIC = 3,
    OBJC_ASSOCIATION_RETAIN = 01401,
    OBJC_ASSOCIATION_COPY = 01403
};
typedef uintptr_t objc_AssociationPolicy;

objc_AssociationPolicy是一个枚举类型的数据结构定义了OBJC_ASSOCIATION_ASSIGNOBJC_ASSOCIATION_RETAIN_NONATOMICOBJC_ASSOCIATION_COPY_NONATOMICOBJC_ASSOCIATION_RETAINOBJC_ASSOCIATION_COPY这样五个关联对象特性,每个特性的描述如下:

  • OBJC_ASSOCIATION_ASSIGN,给关联对象指定弱引用,相当于@property(assign)@property(unsafe_unretained)

  • OBJC_ASSOCIATION_RETAIN_NONATOMIC,给关联对象指定非原子的强引用,相当于@property(nonatomic,strong)或@property(nonatomic,retain)

  • OBJC_ASSOCIATION_COPY_NONATOMIC,给关联对象指定非原子的copy特性,相当于@property(nonatomic,copy)

  • OBJC_ASSOCIATION_RETAIN,给关联对象指定原子强引用,相当于@property(atomic,strong)或@property(atomic,retain)

  • OBJC_ASSOCIATION_COPY,给关联对象指定原子copy特性,相当于@property(atomic,copy)

示例代码

创建一个NSObject名为AssociatedObject的Category,向其中关联一个叫做associatedObject的属性。

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),);
}

@end

说明:

(1)引入#import <objc/runtime.h>的头文件

(2)在头文件中使用@property,对应的.m文件中使用@dynamic

(3)key值可以使用@selector(associatedObject),也可以使用 static const void *AssociatedObjectKey = &AssociatedObjectKey;,推荐使用前者

小结

(1)使用关联,我们可以不用修改类的定义而为其增加存储空间,在对于无法访问到类的源码的时候非常有用

(2)关联是通过关键字来进行操作的,因而可以为任何对象增加任意多的关联,每个都使用不同的关键字即可。

(3)关联是可以保证被关联的对象在关联对象的整个生命周期都是可用的。

延伸阅读

1、《objc_setAssociatedObject通过alert传值》

2、《自定义NSIndexPath — 給Category添加property》

3、《当property遇上category》

最近的文章

Objective-C中的Method Swizzling

Objective-C对象在收到消息之后会经过Dynamic Message Dispatch System(动态消息派发系统)来进行处理,该系统会查出消息对应的方法并执行其代码。那么对于给定@selector名称相对应的方法是否可以在运行期可以动态改变呢?如果能善用这个特性,则可发挥出巨大优势,因为我们可以不需要源码也不需要通过继承子类来覆写对应的方法就能改变这个类本身的功能。没错,Objective-C中确实提供了这样的操作,这就是我们这里会介绍到的Method Swizzling(方...…

iOS继续阅读
更早的文章

微信公众平台开发之开启开发者模式

说起来接触微信公众平台账号开发差不多快有半年了,在这期间利用零散的时间也开发了个企业服务号。经过这个公众账号的开发,对目前微信公众平台的开放的API算是比较熟悉了,对于常见的消息类型(text、news、music、voice、location等)等都有了一些认识和在使用过程中的技巧有了一定的认识。在开发过程中遇到的一些问题也有了一些领悟,所以想将一些经验分享出来,让大家共同进步。开发者模式配置1、在浏览器中输入https://mp.weixin.qq.com或点此打开微信后台界面2、申请...…

WeChat继续阅读