Objective-C——关联对象
动态语言
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——关联对象的更多相关文章
- Effective Objective-C 2.0 — 第10条:在既有类中使用关联对象存放自定义数据
可以通过“关联对象”机制来把两个对象连起来 定义关联对象时可指定内存管理语义,用以模仿定义属性时所采用的“拥有关系”与“非拥有关系” 只有在其他做法不可行时才应选用关联对象,因为这种做法通常会引入难于 ...
- ios 关联对象运用 objc_setAssociatedObject
点按钮的时候,给alertView添加一个关联对象(被点击这个按钮), objc_setAssociatedObject(alert, &kRepresentedObject, sender, ...
- 使用关联对象(AssociatedObject)为UIButton添加Block响应
在开发中,要给UIButton添加点击事件的话,通常的做法是这样的 UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; [ ...
- Mybatis之ResultMap一个简短的引论,关联对象
基础部分能够查看我的还有一篇博客http://blog.csdn.net/elim168/article/details/40622491 MyBatis中在查询进行select映射的时候.返回类型能 ...
- iOS开发--Runtime的简单使用之关联对象
一.Runtime关联对象的方法简介: 在<objc/runtime.h>中,有三个关联的方法,分别是: objc_setAssociatedObject objc_getAssociat ...
- 小解系列-自关联对象.Net MVC中 json序列化循环引用问题
自关联对象在实际开发中用的还是比较多,例如常见的树形菜单.本文是自己实际的一个小测试,可以解决循环引用对象的json序列化问题,文笔不好请多见谅,如有错误请指出,希望有更好的解决方案,一起进步. 构造 ...
- MyBatis之ResultMap简介,关联对象
MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap,resultType是直接表示返回类型的,而resultMap则是对外部ResultM ...
- hibernate关联对象的增删改查------查
本篇博客是之前博客hibernate关联对象的增删改查------查 的后继,本篇代码的设定都在前文已经写好,因此读这篇之前,请先移步上一篇博客 //代码片5 SessionFactory sessi ...
- obj-c编程19:关联对象
对于一些无法子类化的实例对象来说,如果希望将一个对象与其绑定该如何做呢? 以下示例虚构了一个HyConsoleAlert类,User类将会使用该类在控制台显示定制的告警.如果User中包括多个Aler ...
- Django ORM中,如何使用Count来关联对象的子集数量
示例models 解决方法 有时候,我们想要获取一个对象关联关系的数量,但是我们不要所有的关联对象,我们只想要符合规则的那些关联对象的数量. 示例models # models.py from dja ...
随机推荐
- 关于构造函数及参数执行顺序说明(c#)
原文:https://blog.csdn.net/junmail/article/details/83249186 构造函数的执行顺序: 子类静态变量>子类静态构造函数>子类非静态变量&g ...
- String类的转换功能
/* * String类的转换功能 * char[] toCharArray():把字符串转换为字符数组 * String toLowerCase():把字符串转换为小写字符串 * String to ...
- noip模拟赛 业务办理
[问题描述]在银行柜台前,有 n 个顾客排队办理业务. 队伍中从前往后,第 i 位顾客办理业务需要ti 分钟时间. 一位顾客的等待时间定义为:队伍中在他之前的所有顾客和他自己的办理业务时间的总和.第 ...
- 转载 - PowerDesigner(CDM—PDM—SQL脚本的转换流程)
出处: http://jbeduhai.iteye.com/blog/338579 由于图片复制上去不显示,如想看内容及图片详情,请下载附件 PowerDesigner数据模型(CDM—PDM—SQL ...
- 所有在Linux系统下 arp -d $ip 命令只能清除一个IP地址的对应MAC地址缓存,可以使用组合命令操作。
https://blog.csdn.net/u011641885/article/details/48175239 https://blog.csdn.net/zj0910/article/detai ...
- 在docker上安装运行mysql实例
ps:实验环境是:CentOS Linux release 7.3 64位1.获取mysql镜像从docker hub的仓库中拉取mysql镜像docker pull mysql查看镜像docker ...
- Hadoop 究竟能做什么?
http://hi.baidu.com/jiuxiaoyao/item/ff0a19e5b09a953a87d9def3 现在好像大家都在讲 大数据 云计算 hadopp .那么hadoop究竟能做些 ...
- excel 补全全部空格
首先全选列或者选中某列,按F5键.再按"定位条件„"button,选择空值,这样就把全部列的空格选中了,然后直接输入"你想要替换的值",再按Ctrl + 回车
- 使用Jsoup解析和操作HTML
jsoup 简单介绍 jsoup 是一款 Java 的HTML 解析器,可直接解析某个URL地址.HTML文本内容.它提供了一套很省力的API,可通过DOM.CSS以及类似于jQuery的操作方法来取 ...
- JavaScript解析顺序和变量作用域
JavaScript基础之变量作用域. 一. 1.全局变量:全局变量的意思就是,在代码的不论什么地方都能够訪问到.注意:未定义 直接赋值的变量拥有全局属性. 2.局部变量:局部变量的意思就是,变量的作 ...