我知道我们可以使用关联引用来调用类别中的类似ivar的行为。但是,无法在类别中声明新的ivars背后的具体原因是什么?
是因为我们会入侵班级的私人空间吗?或者还有其他原因吗?如果是的话,我会很感激一个例子,它显示了在类别中声明ivars的能力,可以打破它所破坏的任何内容。
答案 0 :(得分:25)
将Objective-C的ivars想象成一个普通的旧C结构。当您实例化一个类的实例时,会创建一个足够大的内存块来保存该结构。
假设你有NSString
。编译了大量现有代码以使用NSString
。很多代码都内置在库和框架中。已编译的代码是在知道NSString
的ivars占用X个字节并且在该内存中的某些给定偏移量的情况下创建的。
现在在您自己的小项目中,我们假设您在NSString
上创建了一个类别,并希望添加一个ivar。理论上,项目中包含该类别头文件的任何代码都知道此“新”NSString
(加类别)的大小需要X + Y字节。这很像一个子类。这个新编译的代码可以正确处理额外的ivar。
但是所有预编译的代码,库和框架都不会知道额外的ivars。当在那里创建NSString
个实例时,内存只有X个字节,而不是X + Y个字节。随着您的应用程序代码获取对该较小内存块的引用并尝试访问类别ivar的字节,随之发生混乱。事情会好转。
使用一个普通的旧子类,事情可行,因为任何可以使用子类'ivars的代码都知道子类的ivars。但是对于一个类别,预先存在的代码不知道添加内容,也不会为它们正确创建空间。
我想我应该指出以上所有内容都是一个有根据的猜测。我完全错了。这似乎至少是合理的。 :)