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 ...
随机推荐
- Spring SpEL 各种写法示例
项目路径 先说一下三个bean都有哪些属性 Address.java private String city;//城市 private String street;//街道 Car.java priv ...
- BNUOJ 33898 Cannon
Cannon Time Limit: 1000ms Memory Limit: 65535KB This problem will be judged on HDU. Original ID: 449 ...
- CodeForces 1000F One Occurrence
You are given an array $a$ consisting of $n$ integers, and $q$ queries to it. $i$-th query is denote ...
- Maven项目pom.xml报错
1.org.apache.maven.archiver.MavenArchiver.getManifest报错 pom.xml第一行报错,如图: 解决办法: 第一步: help ->Instal ...
- MVC之查询demo
上篇已经说过怎样建立MVC项目.这次主要讲述样例的实现. 其基本的功能就是从数据库中查询一些基本信息. 前边我们已经将实体引入到了项目中,这时Model目录中已经出现了我们建立的newsSystem. ...
- 输入两个整数n 和m,从数列1,2,3.......n 中任意取几个数, 使其和等于m ,要求将当中全部的可能组合列出来
中兴面试题之中的一个.难度系数中. 题目描写叙述例如以下:输入两个整数n 和m,从数列1,2.3.......n 中任意取几个数, 使其和等于m ,要求将当中全部的可能组合列出来. 逻辑分析: 1.比 ...
- ZOJ 3888 Twelves Monkeys (预处理+优先队列)
题目链接:ZOJ 3888 Twelves Monkeys 题意:题目描写叙述起来比較绕,直接讲案例 9 3 3 9 1 6 1 4 1 6 7 2 输入n,m,q.n限制了你询问的年份,m台时光机, ...
- LeetCode 141. Linked List Cycle (链表循环)
Given a linked list, determine if it has a cycle in it. Follow up:Can you solve it without using ext ...
- HBase行锁原理及实现
请带着例如以下问题阅读本文. 1.什么是行锁? 2.HBase行锁的原理是什么? 3.HBase行锁是怎样实现的? 4.HBase行锁是怎样应用的? 一.什么是行锁? 我们知道.数据库中存在事务的概念 ...
- CI框架下CSS和JS的路径问题
注意:CI框架下的CSS和JS的引用必须放在框架外面,比如,可建立resource文件夹与application同级,用来封装CSS和JS. 在view层用resource里面CSS和JS可采用以下几 ...