Objective-C中的属性和实例variables

我对Objective-C中的属性和实例variables感到困惑。

我是通过Aaron Hillegass的“Mac OS Xcocoa编程”的一半,一切都是合乎逻辑的。 你会像这样声明一个类:

@class Something; @interface MyClass : NSObject { NSString *name; NSArray *items; Something *something; IBOutlet NSTextField *myTextField; } @property (nonatomic, retain) NSString *name; @property (nonatomic, retain) NSArray *items; 
  • 由于其他对象需要操作我们的nameitems实例variables,因此我们使用@property / @synthesize为它们生成访问器/修改器。 在我们的类中,我们不使用访问器/增变器 – 我们只是直接与实例variables交互。

  • something只是一个实例variables,我们将在我们的类中使用,因为没有其他人需要使用它,所以我们不会为它创build一对访问器和增变器。

  • 我们需要在UI中与文本字段交互,所以我们为它声明一个IBOutlet ,连接它,然后完成。

一切都很合乎逻辑

但是,在iPhone世界里,事情似乎有所不同。 人们为每个实例variables声明属性,为IBOutlets声明属性,并使用访问器/增变器与类中的实例variables进行交互(例如,它们会写[self setName:@"Test"]而不是name = @"Test" ) 。

为什么? 到底是怎么回事? 这些差异是iPhone特有的吗? 为所有实例variables声明属性,为IBOutlets声明属性以及在你自己的类中使用访问器/修改器有什么优势?

在iPhone世界里,没有可用的垃圾回收器。 你必须仔细pipe理内存与引用计数。 考虑到这一点,请考虑以下区别:

 name = @"Test"; 

 self.name = @"Test"; // which is equivalent to: [self setName: @"Test"]; 

如果直接设置实例variables,而没有事先考虑,则将丢失对前一个值的引用,并且无法调整其保留计数(应该手动release它)。 如果通过属性访问它,则会自动为您处理,同时递增新分配的对象的保留计数。

根本的概念不是iPhone的具体情况,但在没有垃圾收集器的环境中,它变得至关重要。

属性用于为实例variables生成访问器,没有魔法发生。

您可以手动执行相同的访问器。

你可以在Aaron Hillegass的书中find3个成员variables的内存pipe理策略的例子。 他们是assign/copy/retain 。 您可以根据给定的variablesselect其中的一个。

我假设你了解Objective-C中的内存pipe理

访问者隐藏每个variables的内存pipe理的复杂性和差异。

例如:

 name = @"Test" 

是一个简单的赋值, name现在持有对NSString @"Test"引用。 但是,您可以决定使用copyretain 。 无论您select访问器的哪个版本的内存pipe理都隐藏了复杂性,并且始终使用(或类似)访问该variables:

 [self setName:@"Test"] [self name] 

现在setName:可以使用assign/copy or retain ,不必担心。

我的猜测是,iPhone教程使用属性,使新开发人员更容易跳过内存pipe理(即使它可以方便地生成具有属性的适当的访问器,而不是每次手工实现它们)。

但是,在iPhone世界里,事情似乎有所不同。 人们为每个实例variables声明属性,为IBOutlets声明属性,并使用访问器/增变器与类中的实例variables进行交互(例如,它们会写[self setName:@"Test"]而不是name = @"Test" ) 。

这不是iPhone特有的。 除了init方法和dealloc方法外,最好总是使用你的访问器。 主要的好处,特别是在Mac(与cocoa绑定),是使用您的访问者意味着免费的KVO通知。

人们为什么“为每个实例variables声明属性”的原因很可能是他们所有的实例variables都是他们想要公开的属性。 如果他们有一些他们想保持私有的东西,他们不会在头文件中为它声明一个属性。 (但是,他们可能会在实现文件的类扩展中为它创build一个属性,以获得上述免费的KVO通知。)

在我看来,宣布网点的属性是矫枉过正的。 我不明白这一点。 如果你没有创build属性,那么nib加载器将通过直接的实例variables访问来设置sockets,这对于这个任务来说是很好的。

我认为现代化发展已经非常有力地确定,确定和应用最佳实践。

在这些最佳实践中,我们发现连续性和一致性。

除了在initdealloc方法中争论使用访问器之外,访问者通常应该始终使用访问器(在一个类的内部和外部)来获得它们提供的好处,包括封装 ,多态var实现(它们都允许抽象和重构)并促进这些最佳做法的连续性和一致性。 面向对象的语言的基本好处是以这种方式做事情,并充分利用语言的能力。 任何高级程序员通常都会certificate,在编码方面始终保持一致是经常被忽略的好处。

你可以这样写

 //MyClass.h @class Something; @interface MyClass : NSObject @property (nonatomic, strong) NSString *name; @property (nonatomic, strong) NSArray *items; @end //MyClass.m @interface MyClass() @property (nonatomic, strong) IBOutlet NSTextField *myTextField; @property (nonatomic, strong) Something *something; @end