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 中的关联对象相关推荐

  1. [iOS]-Category、Extension和关联对象

    目录: 参考的博客: 前言 一.Category分类 Extension扩展 Category的实质 Category结构体 将分类转成C++看起 对象方法列表结构体 类方法列表结构体 协议列表结构体 ...

  2. 【iOS】—— 分类,扩展和关联对象

    分类,扩展和关联对象 文章目录 分类,扩展和关联对象 分类和扩展 分类概念 扩展概念 两者区别 分类的实质 关联对象 通过关联对象给分类添加属性 关联对象的用处 关联对象的API 给声明的属性添加se ...

  3. 通过Runtime源码了解关联对象的实现

    原文链接 在iOS开发中,Category是经常使用到的一个特性,合理的使用Category能够减少繁琐代码,提高开发效率.在使用Category时,有经验的开发者应该都知道,在Category中是无 ...

  4. 关联对象的实现原理【OC】

    前言 AssociationedObject多用于在Category中为特定类扩展成员变量,也有用于在运行时为某些对象动态创建成员变量.AssociationedObject可以说是一种特殊的成员变量 ...

  5. [OC学习笔记]分类和关联对象源码解析

    我们平时在开发的时候经常会使用分类来添加方法.协议.属性,但在添加属性的时候属性是不会自动生成成员变量的,这时候我们就需要关联对象来动态存储属性值. 分类 @interface NSObject(St ...

  6. 关联对象 AssociatedObject 完全解析

    关注仓库,及时获得更新:iOS-Source-Code-Analyze Follow: Draveness · Github 我们在 iOS 开发中经常需要使用分类(Category),为已经存在的类 ...

  7. iOS runtime实战应用:关联对象

    在开始之前建议先阅读iOS runtime的基础理解篇:iOS内功篇:runtime 有筒子在面试的时候,遇到这样一个问题:"如何給NSArray添加一个属性(不能使用继承)",筒 ...

  8. 【iOS】——分类、扩展和关联对象

    目录 一.分类Category和扩展Extension 1.分类Category(运行期) 2.扩展Extension(编译期) 3.分类和扩展的区别 二.分类Category的实质 1.分类的结构 ...

  9. 【iOS开发】——Category底层原理、Extension、关联对象

    [iOS开发]--Category底层原理.Extension.关联对象 Category是什么?它可以用来干什么? Category特点 Category的实质以及实现过程 Category结构体 ...

最新文章

  1. 在 VMware ESXi 5.0 上安装万兆网卡驱动
  2. AI总监王长虎被曝离职,字节跳动AI Lab 再失一将!
  3. 吴恩达演讲直指AI落地三大挑战,并提出解决方案(附视频)
  4. zabbix服务器性能监控工具的安装二
  5. python读excel表格
  6. Unity3D基础39:人物角色模型
  7. hdfs开机启动流程
  8. [04-01]css组合选择器
  9. slz-servlet的引入
  10. java中12个月_C中的12个月日历
  11. python math模块详解
  12. 电路图精简版(web内置画图软件)
  13. 分频电路设计(笔记)
  14. (一)软件开发背景 - 天津市政府采购中心网
  15. 【win10专业版】新建账户激活 Office 2019
  16. 从零开始:小程序开发环境搭建详解
  17. 终于把“翻转课堂”、“微课”和“慕课”说明白了
  18. HTML+CSS制作二级菜单栏
  19. js中ES6新增的数组方法reduce(),和数组去重,降维。
  20. 2016弱校联盟十一专场10.2部分题解

热门文章

  1. linux安装ppp服务器,服务器_最简单的Linux系统上的pptpd服务器安装,1. rpm -qa|grep ppp 检查ppp版本, - phpStudy...
  2. 盘它:1200 天积淀,超 750 篇干货,为你甄选这 100 + 篇精华!
  3. Django REST framework+Vue 打造生鲜超市(五)
  4. 深入浅出,ARCore开发原理
  5. 问答项目---登陆也要做验证!(JS和PHP验证)
  6. arping 帮助——翻译
  7. 成熟的夜间模式解决方案
  8. 微信url schema,deep link
  9. 为什么Nginx性能比Apache高
  10. C#设计模式系列:享元模式(Flyweight)