有时候我们需要在现有的类存放一些额外的信息,通常的做法是继承一个子类,然后定义新增加的属性,然而如果我们为每个需要的类都添加一个类显得太麻烦了,objc提供了一个关联属性的特性,可以给一个对象关联一个属性(做过.NET的朋友一定熟悉附加属性,objc的关联属性与.NET的附加属性有点类似类似)

使用关联属性很简单,下面是几个主要的函数

//设置关联属性
objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy) //获取关联属性
id result = objc_getAssociatedObject(id object, const void *key) //删除所有附加属性
objc_removeAssociatedObjects(id object)

我们声明属性的时候会声明:copy,retain,assign 内存管理方式,在设置关联属性的时候也有,即 objc_setAssociatedObject 的第四个参数

关联类型 等效@property属性

OBJC_ASSOCIATION_ASSIGN

assign

OBJC_ASSOCIATION_RETAIN_NONATOMIC

nonatomic, retain

OBJC_ASSOCIATION_COPY_NONATOMIC

nonatomic, copy

OBJC_ASSOCIATION_RETAIN

retain

OBJC_ASSOCIATION_COPY

copy

关联属性的附加相当于NSDictionary,通过键值对存储,但是有一点跟NSDictionary不一样的是,设置关联对象所用的键(key)是不透明指针(opaque pointer),NSDictionary判断两个Key的isEqual方法判断是否相等,而关联对象只判断两个key的地址是否相等,而不会比较对象具体的值

看看下面例子

    NSString *key1 = @"aaa";
NSString *key2 = [NSString stringWithFormat:@"aaa"];
NSString *key3 = @"bbb"; NSObject *obj = [[NSObject alloc] init]; objc_setAssociatedObject(obj, key1.UTF8String, @"aaa1", OBJC_ASSOCIATION_RETAIN_NONATOMIC);
objc_setAssociatedObject(obj, key2.UTF8String, @"aaa2", OBJC_ASSOCIATION_RETAIN_NONATOMIC);
objc_setAssociatedObject(obj, key3.UTF8String, @"bbb", OBJC_ASSOCIATION_RETAIN_NONATOMIC); id value1 = objc_getAssociatedObject(obj, key1.UTF8String);
id value2 = objc_getAssociatedObject(obj, key2.UTF8String);
id value3 = objc_getAssociatedObject(obj, key3.UTF8String); NSLog(@"value1 = %@", value1);
NSLog(@"value2 = %@", value2);
NSLog(@"value3 = %@", value3);

输出

  这里的key1和key2都是@"aaa",但是取出来的value1和value2却不一样,这是因为key1和key2的地址不一样,在匹配的时候关联对象视为不同的key,所以通常我们在定义关联对象的key的时候使用静态全局变量作为键,这样可以保证地址一致

    static char *key = "aaa";
NSObject *obj = [[NSObject alloc] init]; objc_setAssociatedObject(obj, key, @"aaa1", OBJC_ASSOCIATION_RETAIN_NONATOMIC);
objc_setAssociatedObject(obj, key, @"aaa2", OBJC_ASSOCIATION_RETAIN_NONATOMIC); id value1 = objc_getAssociatedObject(obj, key);
//把原有的值覆盖
id value2 = objc_getAssociatedObject(obj, key); NSLog(@"value1 = %@", value1);
NSLog(@"value2 = %@", value2);

参考文章:

  《Effective Objective C 2.0》编写高质量iOS与OS X代码的52个有效方法 第10条

【iOS】关联属性存取数据的更多相关文章

  1. iOS之Category关联属性

    Objective-C /** 原文件 */ // Person.h #import <Foundation/Foundation.h> @interface Person : NSObj ...

  2. Entity Framework关联查询以及数据加载(延迟加载,预加载)

    数据加载分为延迟加载和预加载 EF的关联实体加载有三种方式:Lazy Loading,Eager Loading,Explicit Loading,其中Lazy Loading和Explicit Lo ...

  3. 李洪强iOS开发-网络新闻获取数据思路回顾

    李洪强iOS开发-网络新闻获取数据思路回顾 01 创建一个继承自AFHTTPSessionManager的工具类:LHQNetworkTool 用来发送网络请求获取数据  1.1 定义类方法返回单例对 ...

  4. EF自动生成的(T4模板) 关联属性元数据修改

    为了实现 T4模板关联属性 不要序列化的问题 就是要在具体的 关联属性上面添加一个元数据 这里利用以前的 Newtonsoft.Json 这个框架为例 效果应该为 就是要在关联属性上面添加元数据  [ ...

  5. hugegraph 数据存取数据解析

    hugegraph 是百度开源的图数据库,支持hbase,mysql,rocksdb等作为存储后端.本文以EDGE 存储,hbase为存储后端,来探索是如何hugegraph是如何存取数据的. 存数据 ...

  6. EF如何操作内存中的数据以及加载相关联表的数据:延迟加载、贪婪加载、显示加载

    之前的EF Code First系列讲了那么多如何配置实体和数据库表的关系,显然配置只是辅助,使用EF操作数据库才是每天开发中都需要用的,这个系列讲讲如何使用EF操作数据库.老版本的EF主要是通过Ob ...

  7. iOS开发网络篇—数据缓存

      iOS开发网络篇—数据缓存 一.关于同一个URL的多次请求 有时候,对同一个URL请求多次,返回的数据可能都是一样的,比如服务器上的某张图片,无论下载多少次,返回的数据都是一样的. 上面的情况会造 ...

  8. WPF/Silverlight深度解决方案:(一)解锁被Storyboard束缚的关联属性

    原文 WPF/Silverlight深度解决方案:(一)解锁被Storyboard束缚的关联属性 如果您在使用WPF/Silverlight进行相关动画开发中使用了Storyboard,并对关联属性进 ...

  9. runtime关联属性示例

    前言 在开发中经常需要给已有的类添加方法和属性,但是Objective-C是不允许给已有类通过分类添加属性的,因为类分类是不会自动生成成员变量的.但是,我们可以通过运行时机制就可以做到了. 本篇文章适 ...

随机推荐

  1. FusionCharts简单教程(六)------加载外部Logo

    一.加载外部文件Logo       在使用FusionCharts时,我们可能需要在加载图像的时候需要在图表中显示标识.图片等等.这里我们可以使用logoURL属性来实现.如: <chart ...

  2. 如何在CRM系统中集成ActiveReports最终报表设计器

    有时候,将ActiveReports设计器集成到业务系统中,为用户提供一些自定义的数据表,用户不需要了解如何底层的逻辑关系和后台代码,只需要选择几张关联的数据表,我们会根据用户的选择生成可供用户直接使 ...

  3. IOS Socket 02-Socket基础知识

    1. 简介 Socket就是为网络服务提供的一种机制 通信的两端都是Socket 网络通信其实就是Socket间的通信 数据在两个Socket间通过IO传输 2. Socket通信流程图 3. 模拟Q ...

  4. osgi 1

    Helloworld入门 准备: eclipse 3.4 需要jar,—— eclipse 自带的,plugin下面有很多,抛开里面的jar,很多都是当前项目不需要的,如果不适用eclipse而是直接 ...

  5. underscore源码阅读记录(二)

    引自underscore.js context参数用法 _.each(list, iteratee, [context]); context为上下文,如果传递了context参数,则把iterator ...

  6. Thrift架构~从图中理解thrift,它事实上是一种远程过程调用

    thrift为我们简化了tcp通讯,它可以使用我们方便的建立各种语言的服务端与客户端,并实现客户端对服务器的远程过程调用,简单的说就是服务器通过thrift架构对外开放一些接口,并自己实现这些接口,如 ...

  7. CentOS6.5下安装JDK

    之前一直没有完全的总结出一篇关于Linux下安装Java的过程,今天正好就整理下. 下载jdk 如果在官网下载比较慢,那么可以到我的云盘分享上,下载jdk 1.8.0的版本: 下载地址参考链接 解压缩 ...

  8. Atitit 项目中的勋章体系,,mvp建设 ,荣典体系建设

    Atitit 项目中的勋章体系,,mvp建设 ,荣典体系建设 1. 荣典体系的标准1 2. 勋章称号1 2.1.1. 授予标准1 3. 政出多门  统一的荣誉制度 2 3.1. 法则规定2 3.2. ...

  9. Atitit 图像处理 常用8大滤镜效果 Jhlabs 图像处理类库 java常用图像处理类库

    Atitit 图像处理 常用8大滤镜效果 Jhlabs 图像处理类库 java常用图像处理类库1.1. 5种常用的Photoshop滤镜,分别针对照片的曝光.风格色调.黑白照片处理.锐利度.降噪这五大 ...

  10. Java项目——模拟电话薄联系人增删改查

    该项目模拟了电话本记录联系人的业务功能,用来练习对数据库的增删改查等操作. 菜单类:Menu -- 用来封装主菜单和个选项的子菜单 Person类: Person--联系人的实体类 TelNoteRe ...