iOS关联对象

Associated Objects(关联对象)或者叫作关联引用(Associative References),是作为Objective-C 2.0 运行时功能被引入到 Mac OS X 10.6 Snow Leopard(及iOS4)系统。与它相关在<objc/runtime.h>中有3个C函数,它们可以让对象在运行时关联任何值:

OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key)
OBJC_EXPORT void objc_removeAssociatedObjects(id object)

为什么这几个方法很有用呢?因为开发者可以通过它们在分类中给已存在的类中添加自定义属性

key 值

关于前两个函数中的 key 值是我们需要重点关注的一个点,这个 key 值必须保证是一个对象级别(为什么是对象级别?看完下面的章节你就会明白了)的唯一常量。一般来说,有以下三种推荐的 key 值:

  1. 声明 static char kAssociatedObjectKey; ,使用 &kAssociatedObjectKey 作为 key 值;
  2. 声明 static void *kAssociatedObjectKey = &kAssociatedObjectKey; ,使用 kAssociatedObjectKey 作为 key 值;
  3. 用 selector ,使用 getter 方法的名称作为 key 值。

我个人最喜欢的(没有之一)是第 3 种方式,因为它省掉了一个变量名,非常优雅地解决了计算科学中的两大世界难题之一(命名)。

关联策略

在给一个对象添加关联对象时有五种关联策略可供选择:

/**
         *  OBJC_ASSOCIATION_ASSIGN
            等价于@property (assign) ,
                 @property (unsafe_unretained)
            弱引用关联对象

         *  OBJC_ASSOCIATION_RETAIN_NONATOMIC
            等价于@property (strong, nonatomic)
            强引用关联对象,且为非原子操作

         *  OBJC_ASSOCIATION_COPY_NONATOMIC
            等价于@property (copy, nonatomic)
            复制关联对象,且为非原子操作

         *  OBJC_ASSOCIATION_RETAIN
            等价于@property (strong, atomic)
            强引用关联对象,且为原子操作

         *  OBJC_ASSOCIATION_COPY
            等价于@property (copy, atomic)
            复制关联对象,且为原子操作

         其中,第 2 种与第 4 种、第 3 种与第 5 种关联策略的唯一差别就在于操作是否具有原子性。
         */
        objc_setAssociatedObject(button, buttonKey, _imgView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

例子:

1、倒入头文件,声明key:

#import <objc/runtime.h>
char* const buttonKey = "buttonKey";

2、设置关联:

if (groupModel.isOpened) {
        UIImageView * _imgView = [[UIImageView alloc]initWithFrame:CGRectMake(10, (44-16)/2, 14, 16)];
        [_imgView setImage:[UIImage imageNamed:@"ico_list"]];
        [sectionView addSubview:_imgView];
        CGAffineTransform currentTransform = _imgView.transform;
        CGAffineTransform newTransform = CGAffineTransformRotate(currentTransform, M_PI/2); // 在现在的基础上旋转指定角度
        _imgView.transform = newTransform;
        objc_setAssociatedObject(button, buttonKey, _imgView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }else{
        UIImageView * _imgView = [[UIImageView alloc]initWithFrame:CGRectMake(10, (44-16)/2, 14, 16)];
        [_imgView setImage:[UIImage imageNamed:@"ico_list"]];
        [sectionView addSubview:_imgView];
        objc_setAssociatedObject(button, buttonKey, _imgView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
  

3、获取关联:

- (void)buttonPress:(UIButton *)sender//headButton点击
{
    GroupModel *groupModel = dataSource[sender.tag];
    UIImageView *imageView =  objc_getAssociatedObject(sender,buttonKey);

    if (groupModel.isOpened) {
            [UIView animateWithDuration:0.3 delay:0.0 options:UIViewAnimationOptionTransitionNone animations:^{
                CGAffineTransform currentTransform = imageView.transform;
                CGAffineTransform newTransform = CGAffineTransformRotate(currentTransform, -M_PI/2); // 在现在的基础上旋转指定角度
                imageView.transform = newTransform;

            } completion:^(BOOL finished) {

            }];

    }else{

            [UIView animateWithDuration:0.3 delay:0.0 options: UIViewAnimationOptionAllowUserInteraction |UIViewAnimationOptionCurveLinear animations:^{

                CGAffineTransform currentTransform = imageView.transform;
                CGAffineTransform newTransform = CGAffineTransformRotate(currentTransform, M_PI/2); // 在现在的基础上旋转指定角度
                imageView.transform = newTransform;

            } completion:^(BOOL finished) {

            }];
        }

    groupModel.isOpened = !groupModel.isOpened;

    [expandTable reloadSections:[NSIndexSet indexSetWithIndex:sender.tag] withRowAnimation:UITableViewRowAnimationAutomatic];
}
时间: 2024-12-25 00:18:43

iOS关联对象的相关文章

iOS runtime实战应用:关联对象

在开始之前建议先阅读iOS runtime的基础理解篇:iOS内功篇:runtime 有筒子在面试的时候,遇到这样一个问题:"如何給NSArray添加一个属性(不能使用继承)",筒子立马蒙逼了,不能用继承,难道用分类?但是分类貌似只能添加方法不能添加属性啊,筒子百思不得其解,直到后来接触到了runtime才恍然大悟. 什么是关联对象 关联对象是指某个OC对象通过一个唯一的key连接到一个类的实例上.举个例子:xiaoming是Person类的一个实例,他的dog(一个OC对象)通过一根

iOS objc_setAssociatedObject 关联对象的学习

今天看了FDTemplateLayoutCell的源码,类别里面相当频繁使用了关联对象,做笔记!!!学套路 主要函数: void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy); id objc_getAssociatedObject(id object, const void *key); void objc_removeAssociatedObjects

iOS中关联对象的简单使用objc_setAssociatedObject

首先看一下此方法接收的参数 objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy) 被关联的对象,下面举的例子中关联到了UIAlertView 要关联的对象的键值,一般设置成静态的,用于获取关联对象的值 要关联的对象的值,从接口中可以看到接收的id类型,所以能关联任何对象 关联时采用的协议,有assign,retain,copy等协议,具体可以参考官方文档 下面就以

Associated Objects(关联对象)

#import <objc/runtime.h> Objective-C开发者应该小心谨慎地遵循这个危险咒语的各种准则.一个很好的原因的就是:混乱的运行时代码会改变运行在其架构之上的所有代码. 从利的角度来讲, <objc/runtime.h> 中的函数具有其他方式做不到的.能为应用和框架提供强大功能的能力.而从弊的角度来讲,它可能会会毁掉代码的sanity meter,一切代码和逻辑都可能被异常糟糕的副作用影响(terrifying side-effects). 因此,我们怀着巨

《Effective Objective-C 2.0》—(第6-10条)—对象、属性、equalToString、关联对象

用OC等面向对象语言编程时,"对象"(object)就是"基本构造单元"(building block),开发者可以通过对象来存储并传递数据.在对象之间传递数据并执行任务的过程就叫做"消息传递"(Messaing). 当应用程序运行起来以后,为其提供相关支持的代码叫做"Objective-C运行期环境"(Objevtive-C runtime),它提供了一些使得对象之间能够传递消息的重要函数,并且包含创建类实例所用的全部逻辑.

iOS 关联的使用

关联是指把两个对象相互关联起来,使得其中的一个对象作为另外一个对象的一部分. 使用关联,我们可以不用修改类的定义而为其对象增加存储空间. 关联是基于关键字的,因此,我们可以为任何对象增加任意多的关联,每个都使用不同的关键字即可. 创建关联 objc_setAssociatedObject   static char Key; NSArray * array =[[NSArray alloc] initWidthObjects:@"red", @"green", @&

运行时之关联对象

头文件: #import <objc/runtime.h> Objective-C 开发者习惯于警惕运行时的东西,理由是运行时改变了运行在它上面代码的实际结构. 另一方面,<objc/runtime.h> 的功能就是为应用或框架增加更强大的新特性,是其他的方式无法 实现的.同时它也可能破坏原来代码的逻辑结构,一切与之可能进行的交互,都将有可怕的副作用. 给我们带来极大的惶恐,因此,我们称之为浮士德,也是NSHipster读者经常被所要求的科目之一: 关联的对象.关联的对象或关联的引

Objective-C——关联对象

动态语言 OC是一种动态语言,它的方法,对象的类型都是到运行的时候才能够确定的.所以这就使得OC存在了关联对象这一强大的机制. 关联对象 所谓关联对象,其实就是我们在运行时对一个已存在的对象上面绑定一个对象,使两个对象变成动态的聚合关系. 关联对象和属性一样有着关键字,以下是关联对象的存储策略: 关联类型 等效的@property属性 OBJC_ASSOCIATION_ASSIGN assign OBJC_ASSOCIATION_RETAIN_NONATOMIC nonatomic,retain

关联对象

一.关联对象所用的方法主要有两个: 1>设置关联对象值:objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy) 2>根据Key取出关联对象的关联值:objc_getAssociatedObject(id object, const void *key) 其中: object:关联的对象, key存和取关联值的键, objc_AssociationPolicy po