Runtime应用(二)使用对象关联为分类增加属性(每个对象的属性互不干扰)
一、对象的关联方法有
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应用(二)使用对象关联为分类增加属性(每个对象的属性互不干扰)的更多相关文章
- 快速上手Runtime(二)之给分类添加属性
我们都知道,分类是不能直接添加属性的,那么我们有时候又需要实现这个功能,那么我们应该怎么办才能为分类添加上属性呢. Runtime给分类添加属性原理 给一个类声明属性,其实本质就是给这个类添加关联,并 ...
- iOS学习之Runtime(二)
前面已经介绍了Runtime系统的概念.作用.部分技术点和应用场景,这篇将会继续学习Runtime的其他知识. 一.Runtime技术点之类/对象的关联对象 关联对象不是为类/对象添加属性或者成员变量 ...
- CUDA运行时 Runtime(二)
CUDA运行时 Runtime(二) 一. 概述 下面的代码示例是利用共享内存的矩阵乘法的实现.在这个实现中,每个线程块负责计算C的一个方子矩阵C sub,块内的每个线程负责计算Csub的一个元素.如 ...
- PHP二维关联数组的遍历方式
采用foreach循环对二维索引数组进行遍历,相对来讲速度更快,效率更高,foreach循环是PHP中专门用来循环数组的.实例也相对简单,多加练习,想清楚程序运行逻辑即可. <?php $arr ...
- {MySQL存储引擎介绍}一 存储引擎解释 二 MySQL存储引擎分类 三 不同存储引擎的使用
MySQL存储引擎介绍 MySQL之存储引擎 本节目录 一 存储引擎解释 二 MySQL存储引擎分类 三 不同存储引擎的使用 一 存储引擎解释 首先确定一点,存储引擎的概念是MySQL里面才有的,不是 ...
- iOS runtime探究(二): 从runtime開始深入理解OC消息转发机制
你要知道的runtime都在这里 转载请注明出处 http://blog.csdn.net/u014205968/article/details/67639289 本文主要解说runtime相关知识, ...
- Phpcms v9专题分类增加模板设置的方法
Phpcms v9专题设置里面,默认专题子分类是无模板设置的,本文教你通过官方论坛给出的教程实现专题分类增加模板设置.先来看看默认专题子分类设置界面: 修改后的的专题子分类设置界面多了模板设置: 修改 ...
- (转发)IOS高级开发~Runtime(二)
一些公用类: @interface ClassCustomClass :NSObject{ NSString *varTest1; NSString *varTest2; NSString *varT ...
- Django中数据传输编码格式、ajax发送json数据、ajax发送文件、django序列化组件、ajax结合sweetalert做二次弹窗、批量增加数据
前后端传输数据的编码格式(contentType) 提交post请求的两种方式: form表单 ajax请求 前后端传输数据的编码格式 urlencoded formdata(form表单里的) ja ...
随机推荐
- 【WPF】使用Popup控件做浮窗/提示框
需求:当鼠标移入某个区域时,弹出一个浮窗,以便用户进行下一步操作. 效果如下图: 当鼠标移入左上角的[多选显示]框内,出现下面的浮窗(悬浮在原UI之上).当在浮窗外点击鼠标左键时,隐藏该浮窗. 由于该 ...
- DHCP服务器-DNS服务器-Samba服务器
DHCP服务器 DHCP在管理网络配置方面很有作用,特别是一个当一个网络的规模较大时,使用DHCP可极大的减少 管理员的工作量. DHCP分为两部分:服务端和客户端.服务端负责集中管理可动态分配的IP ...
- [转]pageX、clientX、screenX、offsetX、layerX、x
参考:http://www.cnblogs.com/xesam/archive/2011/12/08/2280509.html chrome: e.pageX——相对整个页面的坐标e.layerX—— ...
- Win7/Win8下双击执行jar程序的方法
问题 老妈喜欢看小说,又不会下载,于是用Java写了个自己主动下载小说的小程序 我用的Swing UI.直接生成了.jar文件,双击就可以执行 非常诡异的是.用Eclipse直接run能够执行,可是E ...
- C++类的实例化对象的大小之sizeof()
之所以写这篇<C++类的实例化对象的大小之sizeof()>.是由于在參加笔试的时候遇到例如以下这么一道题,当时感觉就是这个一个坑,但.我还是义无反顾的跳了下去,由于存在知识点盲区啊.现, ...
- Cocos2d-x 3.0final 终结者系列教程06-Director和场景跳转
这些天互联网大事不少呀 1.逻辑思维分家(所谓合久必分,分久必合,实属正常.切行切珍惜吧) 2. 锤子手机开卖 (无论你买没买,反正我没买,作为多年Android开发的我深知说的亮点事实上在我看来都 ...
- python中的argsort函数
>>> import numpy >>> help(numpy.argsort) Help on function argsort in module numpy. ...
- TensorFlow基础笔记(11) max_pool2D函数
# def max_pool2d(inputs, # kernel_size, # stride=2, # padding='VALID', # data_format=DATA_FORMAT_NHW ...
- Zookeeper CLI
ZooKeeper命令行界面(CLI)用于与ZooKeeper集合进行交互以进行开发.它有助于调试和解决不同的选项. 要执行ZooKeeper CLI操作,首先打开ZooKeeper服务器(“bin/ ...
- ffplay(2.0.1)中的音视频同步
最近在看ffmpeg相关的一些东西,以及一些播放器相关资料和代码. 然后对于ffmpeg-2.0.1版本下的ffplay进行了大概的代码阅读,其中这里把里面的音视频同步,按个人的理解,暂时在这里作个笔 ...