动态语言

OC是一种动态语言,它的方法,对象的类型都是到运行的时候才能够确定的。所以这就使得OC存在了关联对象这一强大的机制。

关联对象

所谓关联对象,其实就是我们在运行时对一个已存在的对象上面绑定一个对象,使两个对象变成动态的聚合关系。

关联对象和属性一样有着关键字,以下是关联对象的存储策略:

关联类型 等效的@property属性
OBJC_ASSOCIATION_ASSIGN assign
OBJC_ASSOCIATION_RETAIN_NONATOMIC nonatomic,retain
OBJC_ASSOCIATION_COPY_NONATOMIC nonatomic,copy
OBJC_ASSOCIATION_RETAIN retain
OBJC_ASSOCIATION_COPY copy

关联对象主要靠下面三个函数,它们都位于<objc/runtime>下

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

设置关联对象

参数 说明
object 要进行关联的对象
key 一个内存表示,在比较两个关联对象是否相等时,比较的就是内存地址,所以一般用一个全局静态变量表示
value 被关联的对象
policy 存储策略

id objc_getAssociatedObject(id object, void *key)

获取关联对象

void objc_removeAssociatedObjects(id object)

删除关联对象

作用

关联对象一般用于动态的扩展一个对象,但是这一般都是在其他方法不行的事后才会使用,因为关联对象很可能会出现难以查找的bug。

关联对象有时也会用于在category向类添加属性,这点等会儿在分析。

下面Demo在UIAlertView上面动态绑定了一个block,把按钮处理逻辑和alert调用整合在了一起。

static char *AlertKey = "alertKey";

- (void)viewDidLoad {
[super viewDidLoad]; alert = [[UIAlertView alloc] initWithTitle:@"alert" message:@"message" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"other", nil];
} - (IBAction)click:(id)sender { void (^block) (NSInteger) = ^(NSInteger buttonIndex){
if (buttonIndex == ){
NSLog(@"click cancel");
}
else{
NSLog(@"click other");
}
};
objc_setAssociatedObject(alert, AlertKey, block, OBJC_ASSOCIATION_COPY);
[alert show];
} - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
void (^block)(NSInteger) = objc_getAssociatedObject(alertView, AlertKey);
block(buttonIndex);
}

运行程序点击两个按钮分别输出如下

-- ::27.146 Dynamic[:] click other
-- ::28.262 Dynamic[:] click cancel

接下来我们给UIViewController在category中添加一个addition属性

#import "ViewController.h"
#import <objc/runtime.h> @interface UIViewController (Addition) @property(nonatomic ,copy) NSString *addition; @end
#import "UIViewController+Addition.h"

static const void *IndieBandNameKey = &IndieBandNameKey;

@implementation UIViewController (Addition)

-(void)setAddition:(NSString *)addition{
objc_setAssociatedObject(self, IndieBandNameKey, addition, OBJC_ASSOCIATION_COPY);
} -(NSString *)addition{
return objc_getAssociatedObject(self, IndieBandNameKey);
} @end

这里说明一下,这里关联的实际上是形参addition,和属性没有什么关系,写@property 就是为了能够使用‘.’语法。但是@porperty里面的属性存储策略还是要和关联对象一致的,这样不容易造成误解。

所以每次setAddition实际上我们并不是修改了原有内存的值,而是改变了指针指向的地址,这里需要注意一下。

然后修改刚才alert的代码

- (void)viewDidLoad {
[super viewDidLoad]; alert = [[UIAlertView alloc] initWithTitle:@"alert" message:@"message" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"other", nil];
alert.delegate = self;
self.addition = @"addition"; } - (IBAction)click:(id)sender { void (^block) (NSInteger) = ^(NSInteger buttonIndex){
if (buttonIndex == ){
NSLog(@"click cancel");
objc_removeAssociatedObjects(self);
}
else{
NSLog(@"click other");
NSLog(@"%@",self.addition);
}
};
objc_setAssociatedObject(alert, AlertKey, block, OBJC_ASSOCIATION_COPY);
[alert show];
} - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
void (^block)(NSInteger) = objc_getAssociatedObject(alertView, AlertKey);
block(buttonIndex);
}

注意三条加粗的语句,然后我们运行看结果

-- ::54.353 Dynamic[:] click other
-- ::54.353 Dynamic[:] addition
-- ::55.804 Dynamic[:] click cancel
-- ::57.491 Dynamic[:] click other
-- ::57.491 Dynamic[:] (null)

首先我们使用了关联对象,所以点击other的时候会看到打印出了addition。点击cancel的时候又因为我们remove了关联对象,此时再点击other的时候addition就变成null了。

Objective-C——关联对象的更多相关文章

  1. Effective Objective-C 2.0 — 第10条:在既有类中使用关联对象存放自定义数据

    可以通过“关联对象”机制来把两个对象连起来 定义关联对象时可指定内存管理语义,用以模仿定义属性时所采用的“拥有关系”与“非拥有关系” 只有在其他做法不可行时才应选用关联对象,因为这种做法通常会引入难于 ...

  2. ios 关联对象运用 objc_setAssociatedObject

    点按钮的时候,给alertView添加一个关联对象(被点击这个按钮), objc_setAssociatedObject(alert, &kRepresentedObject, sender, ...

  3. 使用关联对象(AssociatedObject)为UIButton添加Block响应

    在开发中,要给UIButton添加点击事件的话,通常的做法是这样的 UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; [ ...

  4. Mybatis之ResultMap一个简短的引论,关联对象

    基础部分能够查看我的还有一篇博客http://blog.csdn.net/elim168/article/details/40622491 MyBatis中在查询进行select映射的时候.返回类型能 ...

  5. iOS开发--Runtime的简单使用之关联对象

    一.Runtime关联对象的方法简介: 在<objc/runtime.h>中,有三个关联的方法,分别是: objc_setAssociatedObject objc_getAssociat ...

  6. 小解系列-自关联对象.Net MVC中 json序列化循环引用问题

    自关联对象在实际开发中用的还是比较多,例如常见的树形菜单.本文是自己实际的一个小测试,可以解决循环引用对象的json序列化问题,文笔不好请多见谅,如有错误请指出,希望有更好的解决方案,一起进步. 构造 ...

  7. MyBatis之ResultMap简介,关联对象

    MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap,resultType是直接表示返回类型的,而resultMap则是对外部ResultM ...

  8. hibernate关联对象的增删改查------查

    本篇博客是之前博客hibernate关联对象的增删改查------查 的后继,本篇代码的设定都在前文已经写好,因此读这篇之前,请先移步上一篇博客 //代码片5 SessionFactory sessi ...

  9. obj-c编程19:关联对象

    对于一些无法子类化的实例对象来说,如果希望将一个对象与其绑定该如何做呢? 以下示例虚构了一个HyConsoleAlert类,User类将会使用该类在控制台显示定制的告警.如果User中包括多个Aler ...

  10. Django ORM中,如何使用Count来关联对象的子集数量

    示例models 解决方法 有时候,我们想要获取一个对象关联关系的数量,但是我们不要所有的关联对象,我们只想要符合规则的那些关联对象的数量. 示例models # models.py from dja ...

随机推荐

  1. Ajax_使用 jQuery 实现Ajax

    [jQuery中的Ajax] 1.jQuery对Ajax操作进行了封装,在jQuery中最底层的方法时 $.ajax().第二层是 load() , $.get()  和 $.post(),第三层是 ...

  2. Java Web学习总结(29)——Java Web中的Filter和Interceptor比较

    1. 背景 在设计web应用的时候,用户登录/注册是必不可少的功能,对用户登录信息进行验证的方法也是多种多样,大致可以认为如下模式:前端验证+后台验证.根据笔者的经验,一般会在前端进行一些例如是否输入 ...

  3. Why does MySQL produce so many temporary MYD files?

    http://dba.stackexchange.com/questions/30505/why-does-mysql-produce-so-many-temporary-myd-files Data ...

  4. hdu poj KMP简单题目总结

    hdu 3336 题意:输入一个字符串求每个前缀在串中出现的次数和 sol:只要稍微理解下next 数组的含义就知道只要把每个有意义的next值得个数加起来即可 PS:网上有dp解法orz,dp[i] ...

  5. noip模拟赛 运

    [问题背景]zhx 和妹子们玩数数游戏.[问题描述]仅包含 4 或 7 的数被称为幸运数.一个序列的子序列被定义为从序列中删去若干个数, 剩下的数组成的新序列.两个子序列被定义为不同的当且仅当其中的元 ...

  6. zoj 3812 状压dp

    转载:http://blog.csdn.net/qian99/article/details/39138329 题意:给出n个物品,每个物品有两种属性Wi,Ti,有q组查询,每组查询要求在n个物品中选 ...

  7. Ubuntu下非常规方法安装绿色软件(压缩包)

    继上一篇http://www.cnblogs.com/EasonJim/p/7117567.html文章中说的常规方式安装的软件,都会自动在命令行及Dash Home中体现. 但是如果是使用压缩包进行 ...

  8. CentOS 7: Install vsftpd

    Install vsftpd All commands should be run with ‘root’ user. Run the following command in terminal to ...

  9. access-list/eigrp等 反掩码计算

    access-list/eigrp等 反掩码计算 原则:地址部分,相同的照写,不同的写"0"     反掩码部分,相同的写"0",不同的写"1&quo ...

  10. Leetcode题解(5):L58/Length of Last Word

    L58: Length of Last Word Given a string s consists of upper/lower-case alphabets and empty space cha ...