从什么时候开始在类别中声明Objective-C 2.0属性?

时间:2010-12-27 16:34:19

标签: objective-c properties categories

我一直认为不能在类别中声明对象属性。 直到我的合作伙伴在我们的应用程序代码中完成它,它似乎工作。

我继续进行SO和谷歌狂欢试图向他解释不,Objective-C类别只能用于添加方法,而不能用于添加属性。我找到了诸如以下的问题:

但后来我在Apple的网站上找到了this link,其中包含有关@property声明的以下内容:

  

属性声明以。开头   关键字@property。 @property可以   出现在方法的任何地方   声明清单在   @interface的一个类。 @property 可以   也出现在宣言中   协议或类别。 (重点补充)

我知道这不起作用:

@interface MyClass ()
NSInteger foobar;
- (void) someCategorizedMethod;
@end

但这会编译:

@interface MyClass ()
@property NSInteger foobar;
- (void) someCategorizedMethod;
@end

我的问题是(a)这里的最佳做法是什么? (b)这是Objective-C 2.0的新功能,而不是使用“真正的”iVar,它只是在幕后使用关联存储来实现这个功能吗?

3 个答案:

答案 0 :(得分:31)

您始终可以在某个类别中声明@property。你不能做的 - 现在仍然不能 - 为类别中的属性声明存储,既不作为实例变量也不通过`@synthesize。

然而....

@interface MyClass () 不是类别。它是一个类扩展,具有明显比类别更具体的角色。

即,类扩展可以用于扩展类的@interface ,这包括可以@synthesized的@properties(包括在现代运行时中合成存储)。

Foo.h:

@interface Foo
@end

Foo.m:

@interface Foo()
@property int x;
@end

@implementation Foo
@synthesize x; // synthesizes methods & storage
@end
  

它只是使用关联存储   在幕后做这项工作?

不 - 它是一个真正的实例变量。现代运行时修复了脆弱的基类问题。


@interface MyClass ()
NSInteger foobar;
- (void) someCategorizedMethod;
@end

上述方法不起作用(如预期的那样),因为foobar实际上是一个全局变量。

如果您将其更改为:

@interface MyClass () {
    NSInteger foobar;
}
- (void) someCategorizedMethod;
@end

然后它将与最新版本的llvm编译器一起使用(带有正确的标志,如@Joshua在评论中指出的那样)。

答案 1 :(得分:1)

一般来说,属性与其他方法没有什么不同。只要使用的ivar在普通类中可用,就没有任何问题。这只是语法糖。

如果自动创建了ivar,事情开始变得更加困难,就像在一些配置中一样。

这里的要点是伊娃的声明独立于财产。

答案 2 :(得分:1)

Assotiative storage是解决方案。 看看这个post