美文网首页ios进阶
Objective - C 关联对象(一) 如何添加"成员变量"

Objective - C 关联对象(一) 如何添加"成员变量"

作者: 爱玩游戏的iOS菜鸟 | 来源:发表于2020-04-20 14:49 被阅读0次

(一)分类 - 能否添加“成员变量”

  • 因为分类底层结构的限制,不能直接添加成员变量到分类中
  • 但可以通过关联对象间接实现

属性 != 变量 分类中添加属性,但并不会添加成员变量及对应的set、get方法

(1)如何获得类似以前成员变量的效果

方法一:定义全局变量 通过set、get方法存取

NSInteger weight_;

-(void)setWeight:(NSInteger)weight{
    weight_ = weight;
}

-(NSInteger)weight{
    return weight_;
}

缺点:多个对象共用一个全局变量

方法二:使用NSDictionary存取不同对象的值

NSMutableDictionary *weights_;

+(void)load{
    weights_ = [NSMutableDictionary dictionary];
}

-(void)setWeight:(NSInteger)weight{
    NSString *key = [NSString stringWithFormat: @"%p",self];//使用self的内存地址作key 保证唯一
    weights_[key] = @(weight);
}

-(NSInteger)weight{
    NSString *key = [NSString stringWithFormat: @"%p",self];
    return [weights_[key] intValue];
}

缺点:1.虽然从外部无法看出区别,但是实际存储位置有区别 成员变量是存储在对象内部,而通过dictionary存储在全局字典对象 2.同时访问存在线程问题 不同的对象在不同的线程同时访问set方法时 3.添加多个变量时 需要定义多个去全局变量

(2)方法三:关联对象

这就是本章的重点,通过关联对象来添加“成员变量”

关联对象提供了以下API:

  1. 添加关联对象 void objc_setAssociatedObject(id object, const void * key, id value, objc_AssociationPolicy policy)
  2. 获得关联对象 id objc_getAssociatedObject(id object, const void * key)
  3. 移除所有的关联对象 void objc_removeAssociatedObjects(id object)
#import <objc/runtime.h>

#define ZQNameKey @"name"
//使用宏 更安全的保证set、get的使用的key一致

@implementation ZQPerson (Test)

static const char ZQName;   //也可以使用static const NSString *ZQName = @"ZQNameKey";
static const char ZQHeight; //但是我们用char 更节约内存 且我们并不需要变量内容 只需要变量地址而已

-(void)setName:(NSString *)name{
    objc_setAssociatedObject(self, &ZQName, name, OBJC_ASSOCIATION_COPY_NONATOMIC);
    //objc_setAssociatedObject(self, ZQNameKey, name, OBJC_ASSOCIATION_COPY_NONATOMIC);
    //方法二:也可以直接使用同一个字符串 因为字符串常量存储在常量区 地址也不会改变
    //objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_COPY_NONATOMIC);
    //方法三:※推荐使用@selector(obj)  返回的是一个指向一个结构体的指针
    //优点:1.可读性更高 2.编译器提示
}

-(NSString *)name{
    return objc_getAssociatedObject(self, &ZQName);
    //return objc_getAssociatedObject(self, ZQNameKey);
    //return objc_getAssociatedObject(self, @selector(name));也能改成return objc_getAssociatedObject(self, _cmd);
    //隐式参数  _cmd = @selector(name) set和get不可同时使用
    // _cmd表示当前方法 因为key要一致 所以不能同时使用
}

-(void)setWeight:(NSInteger)weight{
    objc_setAssociatedObject(self, &ZQHeight, @(weight), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

-(NSInteger)weight{
    return [objc_getAssociatedObject(self, &ZQHeight) intValue];
}

(3)objc_AssociationPolicy 对应的修饰符

image.png

总结一下,key的常见用法

  • static void *MyKey = &MyKey;
    objc_setAssociatedObject(obj, MyKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    objc_getAssociatedObject(obj, MyKey)

  • static char MyKey;
    objc_setAssociatedObject(obj, &MyKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    objc_getAssociatedObject(obj, &MyKey)

  • 使用属性名作为key
    objc_setAssociatedObject(obj, @"property", value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    objc_getAssociatedObject(obj, @"property");

  • 使用get方法的@selecor作为key(set也可以,get更直观)
    objc_setAssociatedObject(obj, @selector(getter), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    objc_getAssociatedObject(obj, @selector(getter))

通过上面多个方法对比,推荐使用方法:

//.h
@property(nonatomic,copy) NSString *name;
@property(nonatomic,assign) NSInteger weight;

@property(nonatomic,class,copy) NSString *sex;

//.m

//实例对象
-(void)setName:(NSString *)name{
    objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

-(NSString *)name{
    return objc_getAssociatedObject(self, _cmd);
}

//类对象
+ (void)setSex:(NSString *)sex{
    objc_setAssociatedObject([self class], @selector(sex), sex, OBJC_ASSOCIATION_COPY_NONATOMIC);

}

+ (NSString *)sex{
    return objc_getAssociatedObject([self class], _cmd);
}

相关文章

  • Objective - C 关联对象(一) 如何添加"成员变量"

    (一)分类 - 能否添加“成员变量” 因为分类底层结构的限制,不能直接添加成员变量到分类中 但可以通过关联对象来间...

  • OC语言之category_关联对象的本质源码解析

    关联对象 能否给分类添加"成员变量"? 使用关联对象技术为分类添加"成员变量" 关联对象添加的"成员变量"添加到了...

  • 关联对象学习

    在没有介绍关联对象之前,先看一道面试题 Category能否添加成员变量?如果可以,如何给Category添加成员...

  • OC关联对象小结(一)

    OC关联对象小结(一) 使用场景 为现有的类添加属性,变量 在Objective-C中可以通过Category给一...

  • 使用 RunTime 给分类添加属性

    通常在分类中只能声明方法,不能添加属性变量,但是其实可以通过关联对象(Objective-C Associated...

  • 关联对象

    能否为分类添加 “成员变量” ? 为分类所添加的成员变量添加在哪里? 所有对象的关联内容都在同一个全局容器内关联对...

  • 关联对象

    如何实现给分类“添加成员变量”? 默认情况下,因为分类底层结构的限制,不能添加成员变量到分类中。可以通过关联对象来...

  • iOS Objective-C 关联对象

    iOS Objective-C 关联对象 1. 关联对象简介 对于关联对象,我们熟悉它的地方就是给分类添加属性。虽...

  • iOS关联对象的底层实现

    分类不能直接添加成员变量,可以通过关联对象间接达到添加成员变量的效果,不能添加成员变量是由于分类的底层结构体是这样...

  • OC底层知识(五) :关联对象

    上一篇博客里面写到如何实现给分类添加成员变量?,在这里咱们通过学习关联对象来解决下。 一、关联对象的常用API 默...

网友评论

    本文标题:Objective - C 关联对象(一) 如何添加"成员变量"

    本文链接:https://www.haomeiwen.com/subject/waahvhtx.html