objc_setAssociatedObject添加的ivar与类声明中的常见ivar相同吗?

时间:2015-12-17 03:44:32

标签: objective-c runtime

@interface XXX : NSObject {
    NSString    *any;
}

与之比较:

objc_setAssociatedObject(self, "any", @"xxx", OBJC_ASSOCIATION_COPY);

它们都放在下面吗?

struct objc_ivar_list *ivars 

2 个答案:

答案 0 :(得分:0)

不,这些是不同的技术。

在编译时定义ivar,并且在分配实例时,为其分配内存空间。 (请记住,NSString*是ivar的类型,因此分配了引用的内存空间,而不是NSString本身的实例。)

关联存储在与实例相关的字典样式存储空间中。

但是,如果要设置一个值,仅在运行时知道其键,请使用键值编码:

[self setValue:@"xxx" forKey:@"any"];

这将执行setter -setAny:,这可能会设置ivar。

声明声明的属性@property)是完全不同的。属性声明声明方法。如果在类或类继续中完成,则在某些情况下合成ivar。在一个类别中它永远不会被合成,因为如果在一个类别中合成是不可能的。

答案 1 :(得分:0)

  

我没有明确表达,这是我的错,我想知道当我使用关联时是否有新的ivar放入objc_ivar_list。现在我明白了.Thx.And。你告诉我,当我在一个班级及其类别中声明一个属性时是否存在任何差异?为什么这样设计 - Max Wang 12月17日7:51

抱歉,我没有足够的声誉来添加评论来回答这个问题。 让我告诉你类和类别中的属性之间的差异。如果在类中声明了属性,编译器将自动为此属性生成setter和getter方法,如您所知。但是,在类别中,即使您被允许为该类声明属性,编译也不会为您生成setter和getter方法。如果您尝试访问类别中声明的属性,Xcode将抛出*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[XXXX setSomeProperty:]: unrecognized selector sent to instance 0x798342c0',因为没有现有方法。这就是为什么我们需要objc_setAssociatedObject和objc_getAssociatedObject来手动生成setter和getter。