类别中的属性

时间:2014-02-20 07:17:46

标签: ios objective-c objective-c-category

为什么当它们和它们的访问器方法都没有被合成时,允许在类别中声明属性?是否涉及任何性能开销?

分类纯粹是编译器技术吗?

我试图了解类别的工作原理。 This只是解释了做什么和不做什么。有没有更详细的消息来源?

编辑:我知道我可以使用关联的引用。这不是我要求的。我想知道为什么这些属性没有合成?如果编译器合成它们,是否存在性能问题或安全问题?如果有,我想知道什么和如何?

4 个答案:

答案 0 :(得分:2)

在进入类别之前,请重新考虑Obj-C中的属性概念:属性是您可以使用访问器以抽象的方式编写和读取的内容。通常,会为其分配一个实例变量,但不需要这样做。 一个属性也可能是有用的,例如,以一致的方式设置多个不同的实例变量,或从多个变量中读取或进行一些计算。

这里的关键事实是:不需要为属性分配实例变量。

类别用作对象行为的扩展,即扩展其方法集,而不更改数据。如果你看到一个抽象意义上的属性,那么它会添加访问器,因此它匹配一个类别的想法。 但是如果你合成它,就会产生一个与类别概念相矛盾的实例变量。

因此,如果你以一种不常见的抽象方式使用它,那么一个类别中的属性才有意义,@synthesize是为了简化常用方法。

答案 1 :(得分:2)

  

为什么允许在类别[...]中声明属性?

属性有很多方面(在编译和运行时)。

  1. 他们总是在课堂上声明一个或两个访问者方法。
  2. 当编译器将点表示法转换为消息时,他们可以更改选择器。
  3. 结合@synthesize指令(或默认情况下),它们可以使编译器合成访问器方法和可选的ivars。
  4. 他们将内省信息添加到运行时可用的类中。
  5. 在类别(或协议)中声明属性并且无法进行合成时,大多数这些方面仍然有用。

      

    分类纯粹是编译器技术吗?

    没有。作为属性的类别既有编译时间也有运行时方面。

    例如,

    类别可以在以后从动态库加载。因此,可能已经有一个类的实例突然添加了新方法。这是类别无法添加ivars的原因之一,因为旧对象会丢失这些ivars以及运行时如何判断是否在添加类别之前或之后创建了对象。

答案 2 :(得分:0)

您可能需要阅读NSHipster,了解如何在类别中实施属性存储。

引用文章:“为什么这有用?它允许开发人员在类别中向现有类添加自定义属性,这是Objective-C的一个明显缺点。”

答案 3 :(得分:0)

@synthesize通知编译器继续并为setter和getter提供默认实现。

表示默认的setter / getters依赖于对象内存在某种存储。

类别不提供任何额外的存储空间,因此默认的setter / getter将没有 place 存储或读取。

另一种方法是使用:

@dynamic

然后为所述属性提供您自己的实现和自己的存储。

一种方法是使用关联对象。 另一种方法是存储/读取一些完全不相关的地方,例如一些可访问的NSUserDefaults字典或...

在某些情况下,对于只读属性,您还可以在运行时重建/计算它们的值,而无需存储它们。