• 可以通过“关联对象”机制来把两个对象连起来
  • 定义关联对象时可指定内存管理语义,用以模仿定义属性时所采用的“拥有关系”与“非拥有关系”
  • 只有在其他做法不可行时才应选用关联对象,因为这种做法通常会引入难于查找的 bug

目的:需要在对象中存放相关信息,方法一,从对象所属的类中继承一个子类,然后改用这个子类对象。

  方法二:关联对象(Associated Object),对象通过“键”来区分。

可以把某对象想象成NSDictionary,把关联到对象上调用[object setObject:value forKey:key] 与 [object objectForKey:key]方法。但是设置关联对象那个时用的键(key)是个“不透明的指针“(opaque pointer),

如果在两个键上调用”isEqual“方法返回值是 YES, 那么NSDictionary就认为两者相等;然而设置关联对象时,二者必须是完全相同的指针才行。鉴于此,在设置关联对象值时,通常使用静态全局变量做键。

下列方法管理关联对象:

  void objc_setAssociatedObject (id object, void*key, id value, objc_AssociationPolicy policy)

  此方法以给定的键和策略为某对象设置关联对象值

   id objc_getAssociatedObject(id object, void*key)

   此方法根据给定的键从某对象中获取相应的关联对象值

  void objc_removeAssociatedObjects(id object)

  此方法移除指定对象的全部关联对象

例子:UIAlertView 类,警告信息,当用户按下按钮关闭该视图时,需要用委托协议(delegate protocol)在处理此动作,但是要想设置好这个委托机制,就得把创建警告视图和处理按钮动作的代码分开。比兔使用UIAlertView 时,一般都会这么写:

  1. - (void)askUserAQuestion {
  2. UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Question"
  3. message:@"What do you want to do?"
  4. delegate:self
  5. cancelButtonTitle:@"Cancel"
  6. otherButtonTiles:@"Continue",nil];
  7. [alert show];
  8. }
  9. // UIAlertViewDelegate protocol method
  10. - (void)alertView:(UIAlertView *)alertView
  11. clickedButtonAtIndex:(NSInteger)buttonIndex
  12. {
  13. if buttoIndex == ) {
  14. [self doCancel];
  15. } else {
  16. [self doContinue];
  17. }
  18. }

如果想在同一个类里处理多个警告信息视图,那么代码就会变得更为复杂,必须在delegate方法中检查传入的 alertView 参数

可以使用关联对象 在创建警告视图的时候直接把处理每个按钮的逻辑都写好:创建完警告视图之后,设定一个与之关联的“块” block,等到执行 delegate 方法是再将其读出来,代码如下

  1. #import <objc/runtime.h>
  2. static void *EOCMyAlertViewKey = "EOCMyAlertViewKey";
  3. - (void)askUserAQuestion {
  4. UIAlertView *alert = [[UIAlertViewalloc] initWithTitle:@"Question"
  5. message:@"What do you want to do?"
  6. delegate:self
  7. cancelButtonTitle:@"Cancel"
  8. otherButtonTitles:@"Continue", nil];
  9. void (^block) (NSInteger) = ^(NSInteger buttonIndex) {
  10. if (buttonIndex == ) {
  11. [self doCancel];
  12. } else {
  13. [self doContinue];
  14. }
  15. };
  16. objc_setAssociateObject(alert, EOCMyAlertViewKey, block, BJC_ASSOCIATION_COPY);
  17. [alert show];
  18. }
  19. // UIAlertViewDelegate protocol method 关联类型等效的@property 属性为
  20. - (void)alertView:(UIAlertView*)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
  21. {
  22. void (^block) (NSInteger) = objc_getAssociateObject(alertView, EOCMyAlertViewKey);
  23. block(buttonIndex);
  24. }

注意:块可能要捕获 (capture)某些变量,这也许会造成“保留环)(retain cycle)

Effective Objective-C 2.0 — 第10条:在既有类中使用关联对象存放自定义数据的更多相关文章

  1. 【从0到1学Web前端】javascript中的ajax对象(一) 分类: JavaScript 2015-06-24 10:18 754人阅读 评论(1) 收藏

    现在最流行的获取后端的(浏览器从服务器)数据的方式就是通过Ajax了吧.今天就来详细的来学习下这个知识吧.如果使用ajax来访问后段的数据,浏览器和浏览器端的js做了那些工作呢?我做了一个图,请大家看 ...

  2. Effective Objective-C 2.0 — 第12条:理解消息转发机制

    11 条讲解了对象的消息传递机制 12条讲解对象在收到无法解读的消息之后会发生什么,就会启动“消息转发”(message forwarding)机制, 若对象无法响应某个选择子,则进入消息转发流程. ...

  3. Effective Objective-C 2.0 — 第9条:以“类族模式”隐藏实现细节

    第9条:以“类族模式”隐藏实现细节 类族模式可以把实现细节隐藏在一套简单的公共接口后面 系统框架中经常使用类族 从类族的公共抽象基类中继承子类时要当心,若有开发文档,则应首先阅读 “类族”(class ...

  4. C# 语言规范_版本5.0 (第10章 类)

    1. 类 类是一种数据结构,它可以包含数据成员(常量和字段).函数成员(方法.属性.事件.索引器.运算符.实例构造函数.静态构造函数和析构函数)以及嵌套类型.类类型支持继承,继承是一种机制,它使派生类 ...

  5. 10条PHP编程习惯助你找工作

    过去的几周对我来说是一段相当复杂的经历.我们公司进行了大裁员,我是其中之一,但却体验到了其中的乐 趣.我从来没有被开除过,所以很难不去想得太多.我开始浏览招聘板块,一个全职PHP程序员的职位很吸引人, ...

  6. Linux系统性能10条命令监控

    Linux系统性能10条命令监控 概述 通过执行以下命令,可以在1分钟内对系统资源使用情况有个大致的了解. uptime dmesg | tail vmstat 1 mpstat -P ALL 1 p ...

  7. 将Web应用性能提高十倍的10条建议

    导读 提高 web 应用的性能从来没有比现在更重要过.网络经济的比重一直在增长:全球经济超过 5% 的价值是在因特网上产生的(数据参见下面的资料).这个时刻在线的超连接世界意味着用户对其的期望值也处于 ...

  8. 转:10条建议让你创建更好的jQuery插件

    在开发过很多 jQuery 插件以后,我慢慢的摸索出了一套开发jQuery插件比较标准的结构和模式.这样我就可以 copy & paste 大部分的代码结构,只要专注最主要的逻辑代码就行了.使 ...

  9. Laxcus大数据管理系统2.0(10)- 第八章 安全

    第八章 安全 由于安全问题对大数据系统乃至当前社会的重要性,我们在Laxcus 2.0版本实现了全体系的安全管理策略.同时我们也考虑到系统的不同环节对安全管理的需求是不一样的,所以有选择地做了不同的安 ...

随机推荐

  1. 进程间通信方式与Binder机制原理

    1, Intent隐式意图携带数据 2, AIDL(Binder) 3, 广播BroadCast 4, 内容提供者ContentProvider --------------------------- ...

  2. pycharm实用快捷键

    提示 CTRL Q: 在参数列表位置,显示可以输入的所有参数. CTRL Q: 查看选中方法的文档字符串 阅读 CTRL -: 折叠当前代码 CTRL +: 展开当前代码 CTRL SHIFT -: ...

  3. 简单的cookie使用

    <html><head><script type="text/javascript">function getCookie(c_name){if ...

  4. struts2 action 页面跳转

    struts2 action 页面跳转 标签: actionstruts2redirect 2013-11-06 16:22 20148人阅读 评论(0) 收藏 举报 (1)type="di ...

  5. bzoj4404: [Neerc2015]Binary vs Decimal

    WC结束了,来补一下这题的题解 首先感谢SC神犇YYY(第一个AC此题的神犇)教我做法 再感谢教YYY做法的Claris大爷 首先,我们发现一个性质,一个合法的数的后缀必定是合法的,所以我们就可以bf ...

  6. asp.net生产环境和开发环境的错误日志包装策略

    对于错误日志的输出,我们借助web.config的两个标志位: <!--全局包装异常处理页面,只有在PageError和Application_Error做清除错误操作才可不跳转--> & ...

  7. ubuntu 设置 NAT 转发

    针对需求: 嵌入式开发中,经常使用板子和笔记本通过网线直连,如果需要板子连接到外网,就比较尴尬. 最简单方法,可以把板子接到局域网内,我们的笔记本通过局域网交换机连接到板子,可是,这样要很多修改 IP ...

  8. python实现自动输入命令回车操作

    苦逼的在sf上等了一天(问题链接),都没人来解答,只好自己想办法,东平西凑还是勉强实现了,记录一下: 安装完python2.7后,在cmd命令行输入python回车,后出现python相关的提示信息, ...

  9. 屠蛟之路_重登数据库大山_SecondDay

    重登数据库大山 屠蛟少年们痛定思痛,(2.0正式改名,咳咳),整顿之后,开启新的屠蛟之路. 然而现实摆在他们面前的是,如果想要往东追击beta怪蛟,就要重新攀登上绵亘数千里.有万丈高的数据库大山脉.不 ...

  10. Possion 分布

    泊松分布的概率函数为: \[P(X=k)=\frac{\lambda^k}{k!}e^{-\lambda},k=0,1,2,\cdots\] 如果 $X_i  \sim P(\lambda_i)$,并 ...