使用当前版本的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
还是有一个很好的用例呢?
根据您的意愿进行投票和投票。
答案 0 :(得分:6)
这里有很多要回答的问题。我打破了它:
正如您所正确指出的那样,编译器的现代版本将为声明的@properties合成后备实例变量。例外情况是在32位Mac上,现有的Objective-C运行时(包括非脆弱的实例变量)不可用。假设您的应用程序未针对32位OS X,则不需要为@property
显式声明支持ivar。
如果你仍然想直接使用ivar,没有相应的@property
(我认为大部分时间都是个坏主意),你当然必须明确声明ivar。
@dynamic
正如你所说的那样,是为了告诉编译器"不要为这个属性合成访问器,我会在运行时自己做这件事"。它并没有经常使用。它使用的一个地方是NSManagedObject
子类,如果你在标题中声明一个建模属性,你不想让编译器抱怨没有为该属性实现访问器,您也不希望它自己生成访问者。 NSManagedObject
在运行时为建模属性生成访问器。自定义CALayer子类的故事类似。
@synthesize
明确告诉编译器合成访问器方法,并且(在iOS和64位Mac上)指定属性的相应ivar。有三种主要情况你还需要使用它:
@synthesize someProperty = _someProperty;
来告诉编译器合成一个ivar。当然,它仍然不会合成访问器方法。或者,您可以明确声明支持ivar。在这种情况下,我赞成使用@synthesize
。答案 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
正如您所描述的那样。
此外,不再需要声明本地实例方法或命令,以使该方法高于使用。