一、对象的关联方法有

1、 void objc_setAssociatedObject(id object, const void *key, id value,objc_AssociationPolicy policy) ,关联对象(将值value与对象object关联起来)

参数key:将来可以通过key取出这个存储的值

参数policy:存储策略(assign、copy、retain)

2、 id objc_getAssociatedObject(id object, const void *key) ,利用参数key将对象中存储的对应值取出

二、关联的作用一,给分类添加属性(下面为每个对象添加属性(可作为对象的标签或存储信息)

大家都知道分类的作用是

/*
分类的作用:在不改变原来类内容的基础上,可以为类增加一些方法
使用注意:
1.分类只能增加方法,不能增加成员变量(其实不然啊)
2.分类方法实现中可以访问原来类中声明的成员变量
3.分类可以重新实现原来类中的方法,但是会覆盖掉原来的方法,会导致原来的方法没法再使用
4.方法调用的优先级:分类(最后参与编译的分类优先) --> 原来类 --> 父类
*/ 我们知道OC比较爽的就是可以添加分类,在分类中添加自己喜欢的方法。可能有人会问了,不能添加属性啊 ,其实不然。用objc_setAssociatedObject(关联)就可以给分类添加属性了

声明代码:

@interface NSObject (CX)
/**
* 为每一个对象添加一个name属性
*/
@property (nonatomic,copy) NSString *name;
/**
* 为每个对象添加一个数组属性
*/
@property (nonatomic,strong) NSArray *books;
@end

实现代码:

// 用一个字节来存储key值,设置为静态私有变量,避免外界修改
static char nameKey;
- (void)setName:(NSString *)name
{
// 将某个值与某个对象关联起来,将某个值存储到某个对象中
objc_setAssociatedObject(self, &nameKey, name, OBJC_ASSOCIATION_COPY_NONATOMIC);
} - (NSString *)name
{
return objc_getAssociatedObject(self, &nameKey);
} static char booksKey;
- (void)setBooks:(NSArray *)books
{
objc_setAssociatedObject(self, &booksKey, books, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
} - (NSArray *)books
{
return objc_getAssociatedObject(self, &booksKey);
}

测试:

NSString *str = @"xx";
str.name = @"oo";
str.books = @[@"xxoo",@"ooxx"];
NSLog(@"%@,%@",str.name,str.books);

打印如下

-- ::37.642 RunTimeTest[:] oo,(
xxoo,
ooxx
)
(lldb)

这样连字符串页具备了一个数组属性。

三、对象关联的另一种作用:在既有类中使用关联对象存放自定义数据

在ios开发时经常会用到UIAlertView类,该类提供了一种视图向用户展示警告信息。该类通过代理协议来处理用户的点击事件,但由于使用了代理就必须把创建警告的视图和处理按钮动作的代码分开,比如说

- (void)showAlertView
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"UIAlertView" message:@"what do you do" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"sure", nil];
[alert show];
} - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if ( == buttonIndex) {
NSLog(@"%@",@"cancel");
}
else if ( == buttonIndex)
{
NSLog(@"%@",@"sure");
}
}

如果想在同一个类里处理多个警告信息视图,我们必须在代理方法中比较点击按钮的索引,并借此编写相应的逻辑,如果能够在创建警告视图的时候直接把处理逻辑的代码写好那将会很便于阅读,这时可以考虑用关联对象,设定一个与alert对象关联的代码块,等到执行代理方法时再将其读取出来

- (void)viewDidLoad {
[super viewDidLoad];
[self showAlertView];
}
static char myAlerViewKey;
- (void)showAlertView
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"UIAlertView" message:@"what do you do" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"sure", nil]; // 将逻辑定义到代码块里面
void(^block)(NSInteger) = ^(NSInteger buttonIndex) {
if (buttonIndex == )
{
NSLog(@"%ld",buttonIndex);
}
else
{
NSLog(@"%ld",buttonIndex);
}
}; // 对象关联
objc_setAssociatedObject(alert, &myAlerViewKey, block, OBJC_ASSOCIATION_COPY); [alert show];
} - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
void(^block)(NSInteger) = objc_getAssociatedObject(alertView, &myAlerViewKey);
block(buttonIndex);
}

每个对象的属性互不干扰

说到这里了在补充一下 其实还可以利用关联来传递数据如

- (void)viewDidLoad {
[super viewDidLoad];
// static const char associatedButtonkey
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setTitle:@"点我" forState:UIControlStateNormal];
[self.view addSubview:btn];
[btn setFrame:CGRectMake(, , , )];
btn.backgroundColor = [UIColor redColor];
[btn addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside];
} -(void)click:(UIButton *)sender
{
NSString *message = @"你是谁";
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"提示" message:@"我要传值·" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil];
alert.delegate = self;
[alert show];
//#import <objc/runtime.h>头文件
//objc_setAssociatedObject需要四个参数:源对象,关键字,关联的对象和一个关联策略。 //1 源对象alert
//2 关键字 唯一静态变量key associatedkey
//3 关联的对象 sender
//4 关键策略 OBJC_ASSOCIATION_ASSIGN
// enum {
// OBJC_ASSOCIATION_ASSIGN = 0, 若引用/**< Specifies a weak reference to the associated object. */
// OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, /**< Specifies a strong reference to the associated object.
// * The association is not made atomically. */
// OBJC_ASSOCIATION_COPY_NONATOMIC = 3, /**< Specifies that the associated object is copied.
// * The association is not made atomically. */
// OBJC_ASSOCIATION_RETAIN = 01401, /**< Specifies a strong reference to the associated object.
// * The association is made atomically. */
// OBJC_ASSOCIATION_COPY = 01403 /**< Specifies that the associated object is copied.
// * The association is made atomically. */
// }; //把alert和message字符串关联起来,作为alertview的一部分,关键词就是msgstr,之后可以使用objc_getAssociatedObject从alertview中获取到所关联的对象,便可以访问message或者btn了
//即实现了关联传值
objc_setAssociatedObject(alert, @"msgstr", message,OBJC_ASSOCIATION_ASSIGN);
objc_setAssociatedObject(alert, @"btn property",sender,OBJC_ASSOCIATION_ASSIGN);
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{ //通过 objc_getAssociatedObject获取关联对象
NSString *messageString =objc_getAssociatedObject(alertView, @"msgstr"); UIButton *sender = objc_getAssociatedObject(alertView, @"btn property");
NSLog(@"%ld",buttonIndex);
NSLog(@"%@",messageString);
NSLog(@"%@",[[sender titleLabel] text]); //使用函数objc_removeAssociatedObjects可以断开所有关联。通常情况下不建议使用这个函数,因为他会断开所有关联。只有在需要把对象恢复到“原始状态”的时候才会使用这个函数。
} 终端打印:
-- ::35.294 test[:]
-- ::35.295 test[:] 你是谁
-- ::35.295 test[:] 点我

Runtime应用(二)使用对象关联为分类增加属性(每个对象的属性互不干扰)的更多相关文章

  1. 快速上手Runtime(二)之给分类添加属性

    我们都知道,分类是不能直接添加属性的,那么我们有时候又需要实现这个功能,那么我们应该怎么办才能为分类添加上属性呢. Runtime给分类添加属性原理 给一个类声明属性,其实本质就是给这个类添加关联,并 ...

  2. iOS学习之Runtime(二)

    前面已经介绍了Runtime系统的概念.作用.部分技术点和应用场景,这篇将会继续学习Runtime的其他知识. 一.Runtime技术点之类/对象的关联对象 关联对象不是为类/对象添加属性或者成员变量 ...

  3. CUDA运行时 Runtime(二)

    CUDA运行时 Runtime(二) 一. 概述 下面的代码示例是利用共享内存的矩阵乘法的实现.在这个实现中,每个线程块负责计算C的一个方子矩阵C sub,块内的每个线程负责计算Csub的一个元素.如 ...

  4. PHP二维关联数组的遍历方式

    采用foreach循环对二维索引数组进行遍历,相对来讲速度更快,效率更高,foreach循环是PHP中专门用来循环数组的.实例也相对简单,多加练习,想清楚程序运行逻辑即可. <?php $arr ...

  5. {MySQL存储引擎介绍}一 存储引擎解释 二 MySQL存储引擎分类 三 不同存储引擎的使用

    MySQL存储引擎介绍 MySQL之存储引擎 本节目录 一 存储引擎解释 二 MySQL存储引擎分类 三 不同存储引擎的使用 一 存储引擎解释 首先确定一点,存储引擎的概念是MySQL里面才有的,不是 ...

  6. iOS runtime探究(二): 从runtime開始深入理解OC消息转发机制

    你要知道的runtime都在这里 转载请注明出处 http://blog.csdn.net/u014205968/article/details/67639289 本文主要解说runtime相关知识, ...

  7. Phpcms v9专题分类增加模板设置的方法

    Phpcms v9专题设置里面,默认专题子分类是无模板设置的,本文教你通过官方论坛给出的教程实现专题分类增加模板设置.先来看看默认专题子分类设置界面: 修改后的的专题子分类设置界面多了模板设置: 修改 ...

  8. (转发)IOS高级开发~Runtime(二)

    一些公用类: @interface ClassCustomClass :NSObject{ NSString *varTest1; NSString *varTest2; NSString *varT ...

  9. Django中数据传输编码格式、ajax发送json数据、ajax发送文件、django序列化组件、ajax结合sweetalert做二次弹窗、批量增加数据

    前后端传输数据的编码格式(contentType) 提交post请求的两种方式: form表单 ajax请求 前后端传输数据的编码格式 urlencoded formdata(form表单里的) ja ...

随机推荐

  1. vsftp移植(待续)

    1. 下载sftp包,解压.如vsftpd-2.3.5.tar.gz2. 编译 进入目录后,修改交叉编译工具(vi Makefile) CC      = arm-none-linux-gnueabi ...

  2. input输入框用el对数字格式化

    <input name="doubleInput" type="text" maxlength="32" id="doubl ...

  3. jQuery EasyUI教程之datagrid应用

    一.利用jQuery EasyUI的DataGrid创建CRUD应用 对网页应用程序来说,正确采集和管理数据通常很有必要,DataGrid的CRUD功能允许我们创建页面来列表显示和编辑数据库记录.本教 ...

  4. 在使用R做数据挖掘时,最常用的数据结构莫过于dataframe了,下面列出几种常见的dataframe的操作方法

    原网址 http://blog.sina.com.cn/s/blog_6bb07f83010152z0.html 在使用R做数据挖掘时,最常用的数据结构莫过于dataframe了,下面列出几种常见的d ...

  5. CSS控制显示图片的一部分

    使用情形:防止反复请求图片资源,我们经常采用一张图片多种效果或内容显示. 假设我有纸张竖直方向的一张图片,竖直y轴方向分别是字母:A,B,C.... 现在分别要显示A.B.C 等字母,我们的CSS可以 ...

  6. TensorFlow基础笔记(14) 网络模型的保存与恢复_mnist数据实例

    http://blog.csdn.net/huachao1001/article/details/78502910 http://blog.csdn.net/u014432647/article/de ...

  7. 【转】MFC 字体LOGFONT

    Windows的字体LOGFONT LOGFONT是Windows内部字体的逻辑结构,主要用于设置字体格式,其定义如下:typedef struct tagLOGFONTA{    LONG      ...

  8. 【转】MFC 无边框窗口的拖动

    MFC中无边框窗口的拖动 void CXXXXDialog::OnLButtonDown(UINT nFlags, CPoint point) { PostMessage(WM_NCLBUTTONDO ...

  9. Hello World! 这是我的第一个 CGI 程序

    Hello World! 这是我的第一个 CGI 程序上面的 C++ 程序是一个简单的程序,把它的输出写在 STDOUT 文件上,即显示在屏幕上.在这里,值得注意一点,第一行输出 Content-ty ...

  10. python cython 模块(1)

    python 是一门动态类型的语音,其开发速度比C,C++等静态语言块, 但是速度慢很多, 而cython 通过混合C和python 的语法,可以提高python代码的运行速度 1) 安装cython ...