Menu

0读书笔记,在既有类中使用关联对象存放自定义数据

突发性我们要求关联一些数量给已部分对象,平时你可能会动用子类化的不二等秘书籍.但是,有望不会直接如此做,因为某个实例可能是您因为某个意义而创办,而你又不想把那些揭示给成立的子类,大概说你只想加到已有的类中去,那么这年你该尝试一下Objective

第十条:在既有类中采用关联对象存放自定义数据

  • C的靶子关联(Associated Objects).

有的时候候须求在指标中贮存相关音信。

当指标被波及的时候,平日会采取三个key来标志.而且对象会钦命一种存款和储蓄战略来治本被积累值.管理攻略如下:

此时大家一般会从指标所属的类中承继二个子类,然后改用那几个子类对象。

typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) { OBJC_ASSOCIATION_ASSIGN = 0, // 指定关联对象为弱引用 OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, // 指定关联对象为强引用,并且为非原子性 OBJC_ASSOCIATION_COPY_NONATOMIC = 3, // 指定关联对象为copy,并且为非原子性 OBJC_ASSOCIATION_RETAIN = 01401, // 指定关联对象为强引用 OBJC_ASSOCIATION_COPY = 01403 // 指定关联对象为copy};

永不全数的情状下都能如此做,一时候类的实例也许是由某种机制所创设的。

论及管理采纳以下情势来举行:

而开荒者无法令这种体制制造出本身所写的子类实例。

// 设置关联对象的key和策略void objc_setAssociatedObject(id object, void *key,id value, objc_AssociationPolicy policy);// 通过给定的key取出关联对象id objc_getAssociatedObject(id object, void *key);// 移除关联的对象void objc_removeAssociatedObjects(id object);

Objective-C中有一项庞大的性情能够消除此难题,那就是“关联对象”(Associated
Object)。

会见关联对象看起来很像NSDictionary的存取值方法

能够给某目标关系大多任何对象,这么些指标通过“键”来区别。

// 设置[object setObject:value forKey:key];// 取出[object objectForKey:key];

存款和储蓄对象值的合乎,能够指明“存款和储蓄计谋”(Strongpolicy),用以爱护相应的“内部存款和储蓄器管理语义”。

唯独她们有一个珍视的分裂点,正是如若是NSDictionary在设置key的时候能够随便使用四个key,不用在意其功能域(scope),而对于Associated Objects来讲那些key必得是全局的.

仓库储存计策由名叫objc_AssociationPolicy的枚举所定义。

在iOS开垦中,大家平常会选拔到二个控件UIAlertView,经常我们会先选用系统提供的初步化方法设置其title,message,delegate和对应的button.那样格外不便利,一时候我们会蒙受那样的标题,大家要依靠客商的点击来做一些处理,譬喻改造一个控件的水彩,那么此时大家就要把该控形成全局的,然后在UIAlertViewdelegate回调方法中去退换颜色.代码如下:

同一的@property属性:若是关联对象产生了质量,那么它就能具有相应的语义。

- changeViewBackGroundColor{ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"友情提示" message:@"你确定要改变view的颜色?" delegate:self cancelButtonTitle:@"取消" otherButtonTitle:@"确定",nil]; [alert show];}// UIAlertViewDelegate protocol method- alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{ if (buttonIndex == 0) { // 改变颜色 } else { // 不改变颜色 }}

【等效的@property属性】

以此艺术看起来很便利,然而假使您须要在同三个筹划调整器里面弹出两个不等的alert,这绝对会让您蛋疼不已,你供给在delegate措施中剖断是哪八个alerView,然后依据分裂的alerView做区别的拍卖,哦对了,最蛋疼的是您须求把这个alerView写成全局的…

OBJC_ASSOCIATION_ASSIGN assign

自然啦,假使您能灵活的利用Associated Objects给系统的UIAlertView提到二个block回调,那么事情就简单多了

OBJC_ASSOCIATION_RETAIN_NONATOMIC nonatomic,retain

呃… …

OBJC_ASSOCIATION_COPY_NONATOMIC nonatomic,copy

是或不是认为要掉渣天了?要起飞了?Let’s Go!!!

OBJC_ASSOCIATION_RETAIN retain

#import <UIKit/UIKit.h>// 声明block类型typedef void(^AlertViewCallBack)(NSInteger buttonIndex);@interface UIAlertView <UIAlertViewDelegate>/** 关联值block,在Category里面写属性自带@dynamic,所以在.m里面已定要对应的实现其setter和getter */@property (copy, nonatomic) AlertViewCallBack callBackBlock;/** 去掉了delegate,加入了block*/+ alertWithCallBackBlock:(AlertViewCallBack)callBackBlock title:(NSString *)title message:(NSString *)message cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ... NS_REQUIRES_NIL_TERMINATION;@end

#import "UIAlertView+Block.h"#import <objc/runtime.h>// 声明全局的keystatic NSString *UIAlertViewKey = @"AlertViewKey";@implementation UIAlertView + alertWithCallBackBlock:(AlertViewCallBack)callBackBlock title:(NSString *)title message:(NSString *)message cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ...{ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:nil cancelButtonTitle:cancelButtonTitle otherButtonTitles:otherButtonTitles, nil]; // 使用系统的宏来实现多参数 NSString *other = nil; va_list args; if (otherButtonTitles) { va_start(args, otherButtonTitles); while ((other = va_arg(args, NSString*))) { [alert addButtonWithTitle:other]; } va_end; } alert.delegate = alert; [alert show]; // 形参block赋值给属性block alert.callBackBlock = callBackBlock;}// setter- setCallBackBlock:(AlertViewCallBack)callBackBlock{ // 设置关联值 [self willChangeValueForKey:@"callBackBlock"]; objc_setAssociatedObject(self, &UIAlertViewKey, callBackBlock, OBJC_ASSOCIATION_COPY); [self didChangeValueForKey:@"callBackBlock"];}// getter- (AlertViewCallBack)callBackBlock{ // 取出关联值 return objc_getAssociatedObject(self, &UIAlertViewKey);}// delegate- alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{ if (self.callBackBlock) { self.callBackBlock(buttonIndex); }}@end

OBJC_ASSOCIATION_COPY copy

行使方法如下:

下列格局能够管理涉及对象:

 // 使用方法,注意这里会造成循环引用,所以记住加__weak,其实更为优雅的方式是使用影子变量 // __weak typeof weakSelf = self; // @weakify; [UIAlertView alertWithCallBackBlock:^(NSInteger buttonIndex) { // @strongify; // 这里就可以直接拿到点击button的index,爽歪歪有木有? // 再也不用写又臭又长的delegate方法了,在不怕需要弹出多个alertView了 // 想怎么弹就怎么弹,想再哪里弹就在哪里弹 if (buttonIndex == 0) { // 确定 NSLog(@"我弹弹弹,弹走鱼尾纹...😂"); } // 如果用到了本类的属性或者调用方法,一定要注意循环引用问题💣💣💣 // 非影子变量 // [weakSelf.view setBackgroundColor:[UIColor redColor]]; // 影子变量 // [self.view setBackgroundColor:[UIColor redColor]]; } title:@"友情提示" message:@"你确定要改变view的颜色?" cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];

此措施以给定的键和宗旨为某指标设置关联对象值

感受到了么?那是个多么庞大的事物!

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

  • Associated objects提供了一种关系三个目的的章程
  • 小心选用内部存储器管理的政策
  • 决不滥用Associated objects,因为那玩意儿一旦出bug很难查找

此办法依照给定的键从某指标中收获相应的关系对象值

id objc_getAssociatedObject (id object, void *key)

此办法移除钦赐对象的有着涉及对象值

void objc_removeAssociatedObjects (id object)

这种艺术很有用,然则只应该在一向不任何的方法完结你想做的政工的时候使用它。

假若滥用,则异常快就能够令代码失控,使其艰辛调节和测量检验。

应用了“块”恐怕会捕获某个变量,那大概会促成“循环引用”(reatain cycle)。

行使这种办法时要特意小心,不可能单纯因为某处能够用该措施就一定要用它。

1.得以透过“关联对象”机制来把多个对象连起来

2.概念关联对象时可内定内部存款和储蓄器管理语义,用以模仿定义属性时所利用的“具备关系”与“非具有关系”

3.唯有在别的做法不可行时,才应选用关联对象,因为这种做法数见不鲜会引进难于查找的bug

【Things to Remember】

1.Associated objects provide a means of linking two objects toghter

2.The memory-management semantics of associated objects can be defined
to mimic owning or nonowning relationships.

3.Associated objects should be used only when another approach is not
possible,since they can easily introduce hard-to-find bugs.

标签:,

发表评论

电子邮件地址不会被公开。 必填项已用*标注

相关文章

网站地图xml地图