18

我知道我们可以使用关联引用在类别中调用类似 ivar 的行为。但是,无法在类别中声明新 ivars 的具体原因是什么?

是因为我们会侵犯班级的私人空间吗?还是有其他原因?如果是的话,我会很感激一个例子,它显示了在类别中声明 ivars 打破它打破的能力。

4

1 回答 1

25

将 Objective-C 的 ivars 想象成一个普通的旧 C 结构。当您实例化一个类的实例时,会创建一个足够大的内存块来保存该结构。

假设您有一个NSString. 大量现有代码被编译使用NSString。很多这些代码都内置在库和框架中。该编译后的代码是在知道 ivarsNSString占用 X 个字节并且在该内存中处于某些给定偏移量时创建的。

现在在您自己的小项目中,假设您创建了一个类别NSString并想要添加一个 ivar。理论上,项目中包含该类别头文件的任何代码都会知道这个“新” NSString(加上类别)的大小需要 X + Y 个字节。这很像一个子类。这个新编译的代码可以正确处理额外的 ivar。

但是所有预编译的代码,库和框架,都不知道额外的 ivars。当NSString在那里创建实例时,内存只有 X 字节,而不是 X + Y 字节。当您的应用程序代码获得对较小内存块的引用并尝试访问类别 ivar 的字节时,就会出现混乱。事情会变得繁荣。

对于普通的旧子类,一切正常,因为任何可以使用子类的 ivars 的代码都知道子类的 ivars。但是对于一个类别,预先存在的代码不知道添加的内容,也不会为它们正确创建空间。

我想我应该说明以上所有内容在很大程度上都是有根据的猜测。我可能完全错了。至少看起来是合理的。:)

于 2014-01-10T04:02:26.910 回答