关联:指把两个对象相互关联起来,使得其中的一个对象作为另外一个对象的一部分
 
一、在类的定义之外为类增加额外的存储空间
       使用关联,我们可以不用修改类的定义而为其对象增加存储空间。这在我们无法访问到类的源码的时候或者是考虑到二进制兼容性的时候是非常有用。
       关联是基于关键字的,因此,我们可以为任何对象增加任意多的关联,每个都使用不同的关键字即可。关联是可以保证被关联的对象在关联对象的整个生命周期  都是可用的(在垃圾自动回收环境下也不会导致资源不可回收)。
 
二、创建关联
     创建关联要使用到Objective-C的运行时函数:objc_setAssociatedObject来把一个对象与另外一个对象进行关联。该函数需要四个参数:源对象,关键字,关联的对象和一个关联策略。
  • 关键字:一个void类型的指针。每一个关联的关键字必须是唯一的。通常都是会采用静态变量来作为关键字。
  • 关联策略:表明了相关的对象是通过赋值,保留引用还是复制的方式进行关联的;还有这种关联是原子的还是非原子的。这里的关联策略和声明属性时的很类似。这种关联策略是通过使用预先定义好的常量来表示的。
 
 
   static char kExtendVarKey; // 键名
    - (void)someCategoryMethod
    {
        NSString *extendVar = objc_getAssociatedObject(self, &kExtendVarKey);
        if(!extendVar){
            extendVar = @"someText";
            objc_setAssociatedObject(self, &kExtendVarKey, extendVar, OBJC_ASSOCIATION_COPY_NONATOMIC);
        }
    }
 
而使用_cmd可以直接使用该@selector的名称,即someCategoryMethod,并且能保证改名称不重复
 - (void)someCategoryMethod
    {
        NSString *extendVar = objc_getAssociatedObject(self, _cmd);
        if(!extendVar){
            extendVar = @"someText";
            objc_setAssociatedObject(self, _cmd, extendVar, OBJC_ASSOCIATION_COPY_NONATOMIC);
        }
    }
 
相关函数:
     objc_getAssociatedObject、objc_setAssociatedObject、objc_removeAssociatedObjects都是Obj-c中的外联方法,
 
  (1)objc_setAssociatedObject 用于给对象添加关联对象,传入 nil 则可以移除已有的关联对象;
  (2)objc_getAssociatedObject 用于获取关联对象;
  (3)objc_removeAssociatedObjects 用于移除一个对象的所有关联对象。
 
注意:objc_removeAssociatedObjects 函数我们一般是用不上的,因为这个函数会移除一个对象的所有关联对象,将该对象恢复成“原始”状态。这样做就很有可能把别人添加的关联对象也一并移除,这并不是我们所希望的。所以一般的做法是通过给 objc_setAssociatedObject 函数传入 nil 来移除某个已有的关联对象。
 
key 值 :这个 key 值必须保证是一个对象级别的唯一常量。
 
以下三种推荐的 key 值:
(1)声明 static char kAssociatedObjectKey; ,使用 &kAssociatedObjectKey 作为 key 值;
(2)声明 static void *kAssociatedObjectKey = &kAssociatedObjectKey; ,使用 kAssociatedObjectKey 作为 key 值;

(3)用 selector ,使用 getter 方法的名称作为 key 值。
第三种省掉了一个变量名,非常优雅地解决了计算科学中的两大世界难题之一(命名)。
 
关联策略
 
结论
 
(1)关联对象的释放时机与被移除的时机并不总是一致的,比如上面的 self.associatedObject_assign 所指向的对象在 ViewController 出现后就      被释放了,但是 self.associatedObject_assign 仍然有值,还是保存的原对象的地址。如果之后再使用 self.associatedObject_assign 就会造成 Crash ,所以我们在使用弱引用的关联对象时要非常小心;
 
(2)一个对象的所有关联对象是在这个对象被释放时调用的 _object_remove_assocations 函数中被移除的。
(3)关联对象与被关联对象本身的存储并没有直接的关系,它是存储在单独的哈希表中的;
 
  1. (4)关联对象的五种关联策略与属性的限定符非常类似,在绝大多数情况下,我们都会使用 OBJC_ASSOCIATION_RETAIN_NONATOMIC 的关联策略,这可以保证我们持有关联对象;
Objective-C的编译器在编译后会在每个方法中加两个隐藏的参数:
一个是_cmd,当前方法的一个SEL指针。_cmd在Objective-C的方法中表示当前方法的selector,正如同self表示当前方法调用的对象实例。
另一个就是用的比较多的self,指向当前对象的一个指针。
 
 

运行时---关联Associated的更多相关文章

  1. [原创]java WEB学习笔记91:Hibernate学习之路-- -HQL 迫切左外连接,左外连接,迫切内连接,内连接,关联级别运行时的检索策略 比较。理论,在于理解

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  2. swift 使用运行时进行属性关联

    1.用OC思想写swift代码真得很爽,swift需要的OC基本上都有,只不过略微改变了一下,例如以前的Foundation库前缀NS全部去掉了,等等...思想其实都一样,不过swift确实非常精简, ...

  3. iOS开发——高级特性&Runtime运行时特性详解

    Runtime运行时特性详解 本文详细整理了 Cocoa 的 Runtime 系统的知识,它使得 Objective-C 如虎添翼,具备了灵活的动态特性,使这门古老的语言焕发生机.主要内容如下: 引言 ...

  4. Objective-C Runtime 运行时之四:Method Swizzling

    理解Method Swizzling是学习runtime机制的一个很好的机会.在此不多做整理,仅翻译由Mattt Thompson发表于nshipster的Method Swizzling一文. Me ...

  5. Objective-C Runtime 运行时之一:类与对象

    Objective-C语言是一门动态语言,它将很多静态语言在编译和链接时期做的事放到了运行时来处理.这种动态语言的优势在于:我们写代码时更具灵活性,如我们可以把消息转发给我们想要的对象,或者随意交换一 ...

  6. 【原】iOS动态性(三) Method Swizzling以及AOP编程:在运行时进行代码注入

    概述 今天我们主要讨论iOS runtime中的一种黑色技术,称为Method Swizzling.字面上理解Method Swizzling可能比较晦涩难懂,毕竟不是中文,不过你可以理解为“移花接木 ...

  7. linux下实现在程序运行时的函数替换(热补丁)

    声明:以下的代码成果,是参考了网上的injso技术,在本文的最后会给出地址,同时非常感谢injso技术原作者的分享. 但是injso文章中的代码存在一些问题,所以后面出现的代码是经过作者修改和检测的. ...

  8. Objective-O Runtime 运行时初体验

    Objective-C语言是一门动态语言,它将很多静态语言在编译和链接时期做的事放到了运行时来处理.这种动态语言的优势在于:我们写代码时更具灵活性,如我们可以把消息转发给我们想要的对象,或者随意交换一 ...

  9. [翻译] WCF运行时架构

    原文地址 http://www.cnblogs.com/idior/articles/971252.html 介绍 WCF具有非常易用的编程模型,服务开发者在掌握ABC的概念后可以很容易的使用WCF去 ...

随机推荐

  1. Ansible常用模块及API

    Ansible安装 安装EPEL作为安装Ansible的yum源(CentOS6.4): rpm -Uvh http://ftp.linux.ncsu.edu/pub/epel/6/i386/epel ...

  2. android学习笔记33——资源ShapeDrawable

    ShapeDrawable ShapeDrawable用于定义一个基本的几何图像(如,矩形.圆形.线条.......). 定义ShapeDrawable的XML文件的根元素是<shape.../ ...

  3. jsp页面中的问题:Date cannot be resolved to a type

    问题如下:写了一个jsp,提示 症状原因:缺date的jar包 解决办法:在jsp开头导入jar包:<%@ page language="java" import=" ...

  4. scala高级内容(一) Case Class

    一. 操作符 自定义操作符 操作付默认左结合调用.除了以:结尾的操作符是右结合调用 object OperaterTest extends App{ val a: myInt = new myInt( ...

  5. 白书 4.1.2 模运算的世界 P291

    1.逆元 这里有个注意事项要说,就是当要求 (a-b)%m 的时候要注意不能直接 (a%m-b%m)%m 原因是得出的值有可能是负数,所以 (a%m-b%m+m)%m 才是正确的. //x,y是引用 ...

  6. 设置session的生存时间

    1.最有效的方法 修改php.ini中  #session的超时时间 session.gc_maxlifetime = 1440  2.通过php去修改这个值 $Lifetime = 3600; $S ...

  7. 转载__Activity的启动模式

    http://www.cnblogs.com/plokmju/p/android_ActivityLauncherMode.html 当然,在Android中,除了在AndroidManifest.x ...

  8. YUV422/YUV420播放

    YUV播放器,directX,VS2008 MFC完成  CSDN下载 http://download.csdn.net/detail/xjt1988xjt/2386621#comment 默认是播放 ...

  9. 不能向Github提交某一類型的文件

    之前在github上建了6個project,但是其中有一個不能提交jar文件,其他的都可以.後來發現原來在項目中有一個叫.gitignore的文件,其他項目里的都是/bin,但是那個不能提交jar的項 ...

  10. 在Linux环境下安装和配置phpmyadmin

    phpmyadmin是一种MySQL的图形化管理工具,该工具允许你在web界面上管理你的mysql数据库,不可谓不方便快捷. 此次安装与配置是在centos 6.4系统下,该系统已部署lnmp环境.关 ...