3

@property在当前版本的 Objective-C 中,使用和声明 ivars 的官方标准和最佳实践是@synthesize什么?有很多关于这个主题的帖子和资源,但其中大多数都在一两年前已经过时了。我最近学会了在类的实现中只在语句块中声明 ivars,这样就不会破坏 OOP 的封装原则,但是在这个时代甚至有必要声明 ivars 吗?什么是可能的用例:

@interface MyClass()
@property (nonatomic) NSString* data;
@end

@implementation MyClass{
    @private
        NSString* _data;
}
@end

有必要的?更进一步,是否有必要使用@synthesize?我的理解是 using@property将自动合成访问器方法和支持 ivars。我做了一些实验,我注意到当我没有NSString* _data', I can still access在我的类实现中声明 _data' 时。这是否意味着声明 ivars 归结为风格问题,取决于程序员的判断?我可以压缩我的代码并在我的实现中删除语句块中的所有 ivar 声明并只@property在我的私有接口中使用吗?如果不是这样,明确声明 ivars 的优点和缺点是什么?

最后,@dynamic. 据我所知,它习惯于对编译器说,“嘿,编译器,不要自动生成访问器方法,如果找不到它的实现也不要担心,我会在运行时提供一个”。是全部@dynamic用于还是有更多用途?

我只是想澄清所有这些事情,因为似乎有很多不同的意见,而且不一定有一个正确的答案。此外,随着 Objective-C 的发展和进步,这些答案会发生变化,因此最好有一份简明且最新的指南。感谢大家!(另外,如果有什么我可以说得更好或更清楚的地方,请告诉我)

编辑:

总之,我要问的是:

1) 有必要用现代 Objective-C 声明 ivars 吗?2)我可以通过使用来实现声明ivars和相应属性的相同效果@property吗?3) @dynamic 是做什么用的?4)我可以完全放弃使用@synthesize它还是有一个好的用例?

在您认为合适的情况下投赞成票和反对票。

4

3 回答 3

6

这里有很多要回答的。我会分解它:

声明 ivars

正如您正确指出的那样,现代版本的编译器将为声明的@properties 合成支持实例变量。例外情况是在 32 位 Mac 上,现代 Objective-C 运行时(包括非脆弱实例变量)不可用。假设您的应用程序不是针对 32 位 OS X,您不需要显式声明支持 ivar@property.

如果你还想直接使用 ivar,不用对应@property(我认为大多数时候这是一个坏主意),您当然仍然必须显式声明 ivar。

@动态的

@dynamic正如您所说的那样,是为了告诉编译器“不要为这个属性合成访问器,我会在运行时自己做”。它并不经常使用。它使用的一个地方是在NSManagedObject子类中,如果您在标头中声明一个建模属性,您不希望编译器抱怨该属性没有访问器的实现,也不希望它自己生成访问器。NSManagedObject在运行时为建模属性生成访问器。自定义 CALayer 子类的情况与此类似。

@合成

@synthesize明确告诉编译器合成访问器方法,以及(在 iOS 和 64 位 Mac 上)指定属性的相应 ivar。在三种主要情况下您仍然需要使用它:

  1. 32 位 Mac 应用程序。
  2. 如果您已经编写了自己的自定义 setter 和 getter(或者只是用于只读属性的 getter)。在这种情况下,编译器不会合成访问器,因为它会看到您的访问器。但是,它也不会合成支持的 ivar。因此,您必须使用@synthesize someProperty = _someProperty;, 来告诉编译器合成一个 ivar。当然,它仍然不会合成访问器方法。或者,您可以显式声明一个支持 ivar。我喜欢使用@synthesize在这种情况下使用。
  3. 如果您想为属性的支持 ivar 使用与默认值不同的名称(带有添加下划线前缀的属性名称)。这是罕见的。我能想到的使用它的主要情况是在转换现有的旧代码时,其中包括直接 ivar 访问并且 ivar 没有下划线前缀。
于 2013-11-07T18:07:15.330 回答
1

首先,@synthesize 在这些场景中消失了:不必再这样做了。

其次,您也不再需要私有 ivar。

所以本质上,你可以只做属性。

控制访问的方式与 MOC 下降之前流行的惯用语相同:将属性放在公共接口中作为只读,然后在私有接口中创建一个读写版本(如上所示,应该只是名称打开和关闭括号)。

还要注意,过去使公共接口混乱的许多东西现在只能在私有接口中,例如 IBOutlets 等,因为控制器将是唯一欺骗它们的东西。

除了在 CoreDate 生成的实体中,我从未见过在任何地方使用过 @dynamic。

对于第一次使用 C++ 的人来说,他们的梦想总是标题/界面只是向类的用户展示他们需要什么,而所有其他细节都将被隐藏,我认为 MOC(现代目标 C)是梦想成真。

顺便说一句,强烈推荐 WWDC Modern Objective C(从 2012 年开始)的介绍会议,今年的会议也很棒。

于 2013-11-07T17:58:24.643 回答
1

当前的最佳实践似乎是对所有 ivars 使用属性,如果要公开它们,则将属性放置在 .h 文件中;如果要公开,则将属性放置在 .m 文件中的类扩展名中(如果对类是本地的)。

@synthesize除非 ivar 需要与下划线前缀的属性名称不同,否则不需要。

是的,@dynamic正如你描述的那样。

此外,不再需要声明局部实例方法或顺序以使该方法高于使用。

于 2013-11-07T18:01:27.027 回答