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

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

有帮助吗?

解决方案

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

假设你有一个 NSString. 。大量现有代码被编译以供使用 NSString. 。许多此类代码都内置在库和框架中。该编译代码是在知道 ivars 的情况下创建的 NSString 占用 X 个字节,并且位于该内存中的某些给定偏移处。

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

但所有预编译的代码、库和框架都不知道额外的 ivars。什么时候 NSString 实例在那里创建,内存只有 X 字节,而不是 X + Y 字节。当您的应用程序代码获取对较小内存块的引用并尝试访问类别 ivar 的字节时,混乱就会随之而来。事情将会蓬勃发展。

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top