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 ...
随机推荐
- Go语言语法说明
Go语言语法说明 go语言中的go func(){}() 表示以并发的方式调用匿名函数func 深入讲解Go语言中函数new与make的使用和区别 前言 本文主要给大家介绍了Go语言中函数new与ma ...
- Leetcode 80.删除重复数组的重复项
删除重复数组的重复项 给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素最多出现两次,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间 ...
- 55. spring boot 服务配置和部署【从零开始学Spring Boot】
Spring Boot 其默认是集成web容器的,启动方式由像普通Java程序一样,main函数入口启动.其内置Tomcat容器或Jetty容器,具体由配置来决定(默认Tomcat).当然你也可以将项 ...
- MongoDB增加用户、删除用户、修改用户读写权限及只读权限(注:转载于http://www.2cto.com/database/201203/125025.html)
MongoDB 增加用户 删除用户 修改用户 读写权限 只读权限, MongoDB用户权限分配的操作是针对某个库来说的.--这句话很重要. 1. 进入ljc 数据库: use ...
- [luoguP1403] [AHOI2005]约数研究(这。。。)
传送门 用类似筛法的原理,就好啦 ——代码 #include <cstdio> int n, ans; int a[1000001]; int main() { int i, j; sca ...
- UVA_1575
https://vjudge.net/problem/UVA-1575 枚举答案(k)..对k质因数分解,质数的指数为cnt[i],若n==A(tot_cnt,tot_cnt) / A(cnt[i]& ...
- 洛谷—— P2330 [SCOI2005]繁忙的都市
P2330 [SCOI2005]繁忙的都市 题目描述 城市C是一个非常繁忙的大都市,城市中的道路十分的拥挤,于是市长决定对其中的道路进行改造.城市C的道路是这样分布的:城市中有n个交叉路口,有些交叉路 ...
- Springmvc 一个简单的管理系统 我所遇到的坑1(持续更新)
前言 好久没有用springmvc写项目了,抽时间写一个简单的springmvc项目 是什么(what)为什么(why)怎么做(how) 1.读书破万卷下笔如有神(理清思路,知识储备和前期整理) 2. ...
- Mybatis错误——Could not find parameter map java.util.Map
错误信息 org.apache.ibatis.builder.IncompleteElementException: Could not find parameter map java.util.Ma ...
- 【转】gcov lcov 覆盖c/c++项目入门
原文: http://www.cnblogs.com/turtle-fly/archive/2013/01/09/2851474.html ------------------------------ ...