runtime(二) 给对象、分类添加实例变量
发布日期:2021-09-03 11:40:16 浏览次数:2 分类:技术文章

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

在开发中有时候想给对象实例添加个变量来存储数据,但又无法直接声明,比如说既有类的分类。这个时候我们就可以通过 关联对象 在运行时给对象关联一个 对象 来存储数据。(注意:并不是真实的添加了一个实例变量)

关联对象 可以给某个对象关联其他对象并用key来区分其他对象。需要注意的是,存储对象的时候要指明 存储策略,用来维护对象的内存管理语义。存储策略是 objc_AssociationPolicy 枚举定义,以下是存储策略对应的 @property属性:

存储策略类型 对应的@property属性
OBJC_ASSOCIATION_ASSIGN weak
OBJC_ASSOCIATION_RETAIN_NONATOMIC strong, nonatomic
OBJC_ASSOCIATION_COPY_NONATOMIC copy, nonatomic
OBJC_ASSOCIATION_RETAIN strong
OBJC_ASSOCIATION_COPY copy

用下面的方法可以管理关联对象:

// 这个方法可以根据指定策略给对象关联对象值void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)// 这个方法可以获取对象关联对象值id objc_getAssociatedObject(id object, const void *key)// 这个方法可以删除指定对象的全部关联对象值void objc_removeAssociatedObjects(id object)复制代码

对于关联对象这个OC特性,我们可以把对象想象成一个 NSDictionary,关联对象需要一个 key( 类型是 opaque pointer,无类型的指针 ) 来区分,我们可以把要添加的变量名作为 key ,把变量的值作为关联的对象来存储到 ”对象“ 这个 NSDictionary 中。 所以,关联对象的

void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)复制代码

方法类似于字典的 [dict setObject: forKey:] 方法。

在存储和获取关联对象时需要用一个相等的 key ,因为是给 Class 的实例对象关联对象,所以一般用静态变量来做 key

说的再多,不如上段代码!

比如说,我们给 NSString 实例加上个 NSDate 类型的 date 变量。什么?给字符串加个日期变量是要干袅?我要给字符串过个生日不行吗! 别闹,举个栗子嘛!(捂脸逃跑~~~)

首先,我们先给 NSString 新建个名为 RT 的 category。 在头文件中有个 NSDate 类型的 date 属性:

//  NSString+RT.h//  runtime#import 
//@interface NSString (RT)//@property (nonatomic, strong) NSDate *date;//@end复制代码

在分类中的属性只会生成 getset 方法,并不会生成变量。 所以我们需要重写 getset 方法,关联对象以变相实现添加变量,在现实文件中:

//  NSString+RT.m//  runtime#import 
#import "NSString+RT.h"//@implementation NSString (RT)//static void *runtime_date_key = "date";- (NSDate *)date{ return objc_getAssociatedObject(self, runtime_date_key);}//- (void)setDate:(NSDate *)date{ objc_setAssociatedObject(self, runtime_date_key, date, OBJC_ASSOCIATION_RETAIN_NONATOMIC);}@end复制代码

需要注意的是,关联对象用到的 key 是个无类型的指针,一般来说是静态来修饰。 另外,给对象关联的只能是对象,如果是 intfloat 等类型需要 NSNumber 进行包装。 因为 date 是强引用和非原子属性,所以关联策略用 OBJC_ASSOCIATION_RETAIN_NONATOMIC

然后执行代码:

NSString *string = @"runtimeTestString";string.date = [NSDate date];NSLog(@"string.date = %@",string.date);复制代码

输出结果:

2016-04-12 21:27:31.099 runtime[2837:103727] string.date = 2016-04-12 13:27:31 +0000复制代码

注意:

  • 定义关联对象时需要指定内存管理语义,用来模拟对象对变量的拥有关系
  • 尽量避免使用关联对象,因为如果出现bug不易于问题排查

我的博客:

转载地址:https://blog.csdn.net/weixin_34186950/article/details/88004573 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:设计模式快速学习(一)工厂模式
下一篇:Pandas多维特征数据预处理及sklearn数据不均衡处理相关技术实践-大数据ML样本集案例实战...

发表评论

最新留言

逛到本站,mark一下
[***.202.152.39]2024年03月27日 05时51分18秒