ios 中的关联对象
2019独角兽企业重金招聘Python工程师标准>>>
关联对象的简单使用:
#import "wangmumu.h"
@interface
wangmumu ()
{
}
@end
static
char
staticString;
@implementation
SHVCarsViewController
- (
void
)viewDidLoad {
[
super
viewDidLoad];
// Do any additional setup after loading the view.
self
.edgesForExtendedLayout=
UIRectEdgeNone
;
self
.tableView.hidden =
YES
;
UIButton
*btn = [[
UIButton
alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];
btn.backgroundColor = [
UIColor
grayColor];
[btn addTarget:
self
action:
@selector
(btnn:) forControlEvents:
UIControlEventTouchUpInside
];
objc_setAssociatedObject(btn, &staticString, @
"aaaa"
, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
[
self
.view addSubview:btn];
}
- (
void
)btnn:(
UIButton
*)btn{
NSString
*str = objc_getAssociatedObject(btn, &staticString);
NSLog
(@
"%@"
,str);
}
/*
objc_setAssociatedObject(btn, &staticString, @"aaaa", OBJC_ASSOCIATION_RETAIN_NONATOMIC);
有四个参数
1.被关联的对象
2.要关联的对象的键值,一般设置成静态的,用于获取关联对象的值
3.要传得值 一般是静态变量
4.关联时采用的协议,有assign,retain,copy等协议 点击进去选取枚举
*/
关联对象(Associated Object)
关联对象是Runtime中一个非常实用的特性,不过可能很容易被忽视。
关联对象类似于成员变量,不过是在运行时添加的。我们通常会把成员变量(Ivar)放在类声明的头文件中,或者放在类实现的@implementation后面。但这有一个缺点,我们不能在分类中添加成员变量。如果我们尝试在分类中添加新的成员变量,编译器会报错。
我们可能希望通过使用(甚至是滥用)全局变量来解决这个问题。但这些都不是Ivar,因为他们不会连接到一个单独的实例。因此,这种方法很少使用。
Objective-C针对这一问题,提供了一个解决方案:即关联对象(Associated Object)。
我们可以把关联对象想象成一个Objective-C对象(如字典),这个对象通过给定的key连接到类的一个实例上。不过由于使用的是C接口,所以key是一个void指针(const void *)。我们还需要指定一个内存管理策略,以告诉Runtime如何管理这个对象的内存。这个内存管理的策略可以由以下值指定:
1
2
3
4
5
OBJC_ASSOCIATION_ASSIGN
OBJC_ASSOCIATION_RETAIN_NONATOMIC
OBJC_ASSOCIATION_COPY_NONATOMIC
OBJC_ASSOCIATION_RETAIN
OBJC_ASSOCIATION_COPY
当宿主对象被释放时,会根据指定的内存管理策略来处理关联对象。如果指定的策略是assign,则宿主释放时,关联对象不会被释放;而如果指定的是retain或者是copy,则宿主释放时,关联对象会被释放。我们甚至可以选择是否是自动retain/copy。当我们需要在多个线程中处理访问关联对象的多线程代码时,这就非常有用了。
我们将一个对象连接到其它对象所需要做的就是下面两行代码:
1
2
3
static char myKey;
objc_setAssociatedObject(self, &myKey, anObject, OBJC_ASSOCIATION_RETAIN);
在这种情况下,self对象将获取一个新的关联的对象anObject,且内存管理策略是自动retain关联对象,当self对象释放时,会自动release关联对象。另外,如果我们使用同一个key来关联另外一个对象时,也会自动释放之前关联的对象,这种情况下,先前的关联对象会被妥善地处理掉,并且新的对象会使用它的内存。
1
id anObject = objc_getAssociatedObject(self, &myKey);
我们可以使用objc_removeAssociatedObjects函数来移除一个关联对象,或者使用objc_setAssociatedObject函数将key指定的关联对象设置为nil。
我们下面来用实例演示一下关联对象的使用方法。
假定我们想要动态地将一个Tap手势操作连接到任何UIView中,并且根据需要指定点击后的实际操作。这时候我们就可以将一个手势对象及操作的block对象关联到我们的UIView对象中。这项任务分两部分。首先,如果需要,我们要创建一个手势识别对象并将它及block做为关联对象。如下代码所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
- (void)setTapActionWithBlock:(void (^)(void))block
{
UITapGestureRecognizer *gesture = objc_getAssociatedObject(self, &kDTActionHandlerTapGestureKey);
if (!gesture)
{
gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(__handleActionForTapGesture:)];
[self addGestureRecognizer:gesture];
objc_setAssociatedObject(self, &kDTActionHandlerTapGestureKey, gesture, OBJC_ASSOCIATION_RETAIN);
}
objc_setAssociatedObject(self, &kDTActionHandlerTapBlockKey, block, OBJC_ASSOCIATION_COPY);
}
这段代码检测了手势识别的关联对象。如果没有,则创建并建立关联关系。同时,将传入的块对象连接到指定的key上。注意block对象的关联内存管理策略。
手势识别对象需要一个target和action,所以接下来我们定义处理方法:
1
2
3
4
5
6
7
8
9
10
11
12
- (
void
)__handleActionForTapGesture:(UITapGestureRecognizer *)gesture
{
if
(gesture.state == UIGestureRecognizerStateRecognized)
{
void
(^action)(
void
) = objc_getAssociatedObject(self, &kDTActionHandlerTapBlockKey);
if
(action)
{
action();
}
}
}
我们需要检测手势识别对象的状态,因为我们只需要在点击手势被识别出来时才执行操作。
从上面的例子我们可以看到,关联对象使用起来并不复杂。它让我们可以动态地增强类现有的功能。我们可以在实际编码中灵活地运用这一特性。
转载于:https://my.oschina.net/u/2329800/blog/652049
ios 中的关联对象相关推荐
- [iOS]-Category、Extension和关联对象
目录: 参考的博客: 前言 一.Category分类 Extension扩展 Category的实质 Category结构体 将分类转成C++看起 对象方法列表结构体 类方法列表结构体 协议列表结构体 ...
- 【iOS】—— 分类,扩展和关联对象
分类,扩展和关联对象 文章目录 分类,扩展和关联对象 分类和扩展 分类概念 扩展概念 两者区别 分类的实质 关联对象 通过关联对象给分类添加属性 关联对象的用处 关联对象的API 给声明的属性添加se ...
- 通过Runtime源码了解关联对象的实现
原文链接 在iOS开发中,Category是经常使用到的一个特性,合理的使用Category能够减少繁琐代码,提高开发效率.在使用Category时,有经验的开发者应该都知道,在Category中是无 ...
- 关联对象的实现原理【OC】
前言 AssociationedObject多用于在Category中为特定类扩展成员变量,也有用于在运行时为某些对象动态创建成员变量.AssociationedObject可以说是一种特殊的成员变量 ...
- [OC学习笔记]分类和关联对象源码解析
我们平时在开发的时候经常会使用分类来添加方法.协议.属性,但在添加属性的时候属性是不会自动生成成员变量的,这时候我们就需要关联对象来动态存储属性值. 分类 @interface NSObject(St ...
- 关联对象 AssociatedObject 完全解析
关注仓库,及时获得更新:iOS-Source-Code-Analyze Follow: Draveness · Github 我们在 iOS 开发中经常需要使用分类(Category),为已经存在的类 ...
- iOS runtime实战应用:关联对象
在开始之前建议先阅读iOS runtime的基础理解篇:iOS内功篇:runtime 有筒子在面试的时候,遇到这样一个问题:"如何給NSArray添加一个属性(不能使用继承)",筒 ...
- 【iOS】——分类、扩展和关联对象
目录 一.分类Category和扩展Extension 1.分类Category(运行期) 2.扩展Extension(编译期) 3.分类和扩展的区别 二.分类Category的实质 1.分类的结构 ...
- 【iOS开发】——Category底层原理、Extension、关联对象
[iOS开发]--Category底层原理.Extension.关联对象 Category是什么?它可以用来干什么? Category特点 Category的实质以及实现过程 Category结构体 ...
最新文章
- 在 VMware ESXi 5.0 上安装万兆网卡驱动
- AI总监王长虎被曝离职,字节跳动AI Lab 再失一将!
- 吴恩达演讲直指AI落地三大挑战,并提出解决方案(附视频)
- zabbix服务器性能监控工具的安装二
- python读excel表格
- Unity3D基础39:人物角色模型
- hdfs开机启动流程
- [04-01]css组合选择器
- slz-servlet的引入
- java中12个月_C中的12个月日历
- python math模块详解
- 电路图精简版(web内置画图软件)
- 分频电路设计(笔记)
- (一)软件开发背景 - 天津市政府采购中心网
- 【win10专业版】新建账户激活 Office 2019
- 从零开始:小程序开发环境搭建详解
- 终于把“翻转课堂”、“微课”和“慕课”说明白了
- HTML+CSS制作二级菜单栏
- js中ES6新增的数组方法reduce(),和数组去重,降维。
- 2016弱校联盟十一专场10.2部分题解
热门文章
- linux安装ppp服务器,服务器_最简单的Linux系统上的pptpd服务器安装,1. rpm -qa|grep ppp 检查ppp版本, - phpStudy...
- 盘它:1200 天积淀,超 750 篇干货,为你甄选这 100 + 篇精华!
- Django REST framework+Vue 打造生鲜超市(五)
- 深入浅出,ARCore开发原理
- 问答项目---登陆也要做验证!(JS和PHP验证)
- arping 帮助——翻译
- 成熟的夜间模式解决方案
- 微信url schema,deep link
- 为什么Nginx性能比Apache高
- C#设计模式系列:享元模式(Flyweight)