博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Effective Objective-C 2.0 — 第10条:在既有类中使用关联对象存放自定义数据
阅读量:7000 次
发布时间:2019-06-27

本文共 2847 字,大约阅读时间需要 9 分钟。

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

- (void)askUserAQuestion {    UIAlertView *alert = [[UIAlertView alloc]  initWithTitle:@"Question"                                                             message:@"What do you want to do?"                                                             delegate:self                                                             cancelButtonTitle:@"Cancel"                                                             otherButtonTiles:@"Continue",nil];            [alert show];}// UIAlertViewDelegate protocol method- (void)alertView:(UIAlertView *)alertView            clickedButtonAtIndex:(NSInteger)buttonIndex{    if (buttoIndex == 0) {           [self doCancel];    } else {            [self doContinue];    }}

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

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

#import 
static void *EOCMyAlertViewKey = "EOCMyAlertViewKey"; - (void)askUserAQuestion { UIAlertView *alert = [[UIAlertViewalloc] initWithTitle:@"Question" message:@"What do you want to do?" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Continue", nil]; void (^block) (NSInteger) = ^(NSInteger buttonIndex) { if (buttonIndex == 0) { [self doCancel]; } else { [self doContinue]; } }; objc_setAssociateObject(alert, EOCMyAlertViewKey, block, BJC_ASSOCIATION_COPY); [alert show];}// UIAlertViewDelegate protocol method 关联类型等效的@property 属性为- (void)alertView:(UIAlertView*)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{ void (^block) (NSInteger) = objc_getAssociateObject(alertView, EOCMyAlertViewKey); block(buttonIndex);}

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

转载于:https://www.cnblogs.com/IDRI/p/5120639.html

你可能感兴趣的文章
ILSVRC
查看>>
matlab超限像素平滑法_脉冲伏安法理论基础
查看>>
arduino 串口读取字符串_Arduino传感器教程 第24章NRF24L01 控制电舵机
查看>>
状态码202_HTTP状态码(HTTP Status Code)
查看>>
sharepoint 2010 网站集定期备份
查看>>
管理SCCM/MDT中的驱动分类
查看>>
java之HashTable
查看>>
Windows Server 2012体验之配置存储池
查看>>
轻松上手移动互联——百度SiteApp建造日志
查看>>
我从跑步中领悟到了什么?
查看>>
你的权限等于你的可见度
查看>>
Gartner:威胁情报的定义
查看>>
redis多实例重启脚本
查看>>
开发人员学Linux(4):使用JMeter对网站和数据库进行压力测试
查看>>
在51系列中data,idata,xdata,pdata的区别
查看>>
【Deeplearning】关注书目
查看>>
【再见RMQ】NYOJ-119-士兵杀敌(三),区间内大小差值
查看>>
loadrunner中Run-time-Setting设置
查看>>
SSL连接建立过程分析(1)
查看>>
port与大全portClose方法
查看>>