一、对象的关联方法有

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. 未找到与约束ContractName,无法打开项目的解决方案

    如果VS2013,在打开解决方案时,报如下错误: “未找到与约束 ContractName Microsoft.Internal.VisualStudio.PlatformUI.ISolutionAt ...

  2. Android—— TextView文字链接4中方法

    转自:http://ghostfromheaven.iteye.com/blog/752181 Android 的实现TextView中文字链接的方式有很多种. 总结起来大概有4种: 1.当文字中出现 ...

  3. win8.1 win10存储设备和驱动器分开显示

    win10同理如下: Windows 8.1不仅将资源管理器重命名为文件管理器,还将用户熟悉的“计算机/我的电脑”改名为“这台电脑”,同时还将原先的布局进行了重构,于是用户最终看到的是这样一个界面: ...

  4. CentOS 6编译安装yum和配置常用的yum源

    安装环境:VPS,CentOS 6 + devel包 一.安装相应的软件 1.安装python 下载Python源码包 [root@akinlau ~]# wget http://www.python ...

  5. DataTable使用技巧:DataRowState

    DataGridView:获取 DataRow 对象的状态,共有5个枚举值. Added 该行已添加到 DataRowCollection 中,AcceptChanges 尚未调用. Deleted ...

  6. UC浏览器调试移动端网站

    准备工作: UC浏览器开发版网址 UC浏览器开发者版下载地址 下载adb_tool 步骤: 1.将adb_tool解压,把里面的文件复制到 C:\Windows\SysWOW64 文件夹下面. 2.运 ...

  7. EasyUI项目中的自定义JS

    自定义方法: (function($) { $.extend($, { //获取下标,删除时使用 getArrayIndex :  function (array,value) { var index ...

  8. sparkr基本操作1

    由于装的sparkr是1.4版本的,老版本的很多函数已经不再适用了. 在2台服务器的组成的集群中测试了一版数据,熟悉下这个api的基本操作.​ libpath <- .libPaths() li ...

  9. i2c驱动笔记

    基于bcm5300x芯片 注册平台总线设备,设备名bcm5300x_i2c,通过名称与驱动进行匹配. 注册平台总线驱动.驱动名称"bcm5300x_i2c",与设备进行匹配. dr ...

  10. par函数fg参数-控制前景色

    fg参数用来控制前景色,其实指的就是x轴和y轴的轴线和刻度线的颜色 在R语言中,会根据fg, col 任何一个参数的值,自动的将两个参数的值设置为相同的值,举个例子: par(fg = "r ...