现代Objective-C(2013)并声明ivars /使用@property,@ dynamic和@synthesize

时间:2013-11-07 17:51:47

标签: objective-c oop instance-variables

使用当前版本的Objective-C,使用@property@synthesize宣布ivars的官方标准和最佳做法是什么?关于这个主题有很多帖子和资源,但大多数帖子和资源在一两年前相当陈旧。我最近学会了在类的实现中只在声明块中声明ivars,以便OOP的封装原则不被打破,但是在这个时代甚至需要声明ivars?在做什么可能的用例:

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

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

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

最后,@dynamic。从我可以收集到的,它曾经对编译器说,“嘿编译器,不要自动生成访问器方法,如果你没有找到它的实现,不要担心,我会在运行时提供一个”。是全部使用@dynamic还是更多呢?

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

编辑:

总之,我问的是:

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

根据您的意愿进行投票和投票。

3 个答案:

答案 0 :(得分:6)

这里有很多要回答的问题。我打破了它:

声明ivars

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

如果你仍然想直接使用ivar,没有相应的@property(我认为大部分时间都是个坏主意),你当然必须明确声明ivar。

@dynamic

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

@synthesize

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

  1. 32位Mac应用程序。
  2. 如果您已经编写了自己的自定义setter和getter(或者只是getterly属性的getter)。在这种情况下,编译器不会合成访问器,因为它会看到你的访问器。然而,它也不会合成背景ivar。因此,您必须使用@synthesize someProperty = _someProperty;来告诉编译器合成一个ivar。当然,它仍然不会合成访问器方法。或者,您可以明确声明支持ivar。在这种情况下,我赞成使用@synthesize
  3. 如果要为属性的支持使用与默认值不同的名称(具有添加的下划线前缀的属性名称)。这很少见。我可以想到使用它的主要情况是在转换现有的旧代码时,包括直接ivar访问以及ivars不以下划线为前缀。

答案 1 :(得分:1)

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

其次,你不再需要私人ivar了。

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

控制访问的方式与在MOC删除之前变得流行的成语相同:将属性作为readonly放入公共接口,然后在私有接口中创建一个readwrite版本(如上所示,应该只是开放和关闭的名称。

另请注意,过去混乱公共接口的许多事情现在只能在私有接口中,例如IBOutlets等,因为控制器将是唯一困扰它们的东西。

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

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

BTW,强烈推荐WWDC现代目标C(2012年)的介绍会,今年也很好。

答案 2 :(得分:1)

目前最好的做法似乎是使用所有ivars的属性将属性放在.h文件中(如果要公开它们)和类扩展名中的.m文件(如果是本地的。)

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

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

此外,不再需要声明本地实例方法或命令,以使该方法高于使用。