Objective-C中的属性和实例变量

Ste*_*son 55 cocoa cocoa-touch properties objective-c instance-variables

我对Objective-C中的属性和实例变量感到困惑.

我在Aaron Hillegass的"Mac OS X的可可编程"中走了一半,一切都是合乎逻辑的.你会声明一个这样的类:

@class Something;

@interface MyClass : NSObject {
    NSString *name;
    NSArray *items;

    Something *something;

    IBOutlet NSTextField *myTextField;
}

@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSArray *items;
Run Code Online (Sandbox Code Playgroud)
  • 由于其他对象需要操作我们的实例nameitems实例变量,我们使用@property/ @synthesize为它们生成访问器/ 更改器.在我们的类中,我们不使用访问器/ mutator - 我们只是直接与实例变量交互.

  • something 只是我们将在我们的类中使用的实例变量,并且由于没有其他人需要使用它,我们不会为它创建一对访问器和变换器.

  • 我们需要在UI中与文本字段进行交互,因此我们声明了IBOutlet它,连接它,我们就完成了.

都很合乎逻辑.

然而,在iPhone世界中,事情似乎有所不同.人们声明属性,为每一个实例变量,用于声明属性IBOutlets,并使用存取/存取器与实例变量相互作用的类别(例如,他们会写[self setName:@"Test"],而不是name = @"Test").

为什么?到底是怎么回事?这些差异是否与iPhone有关?为所有实例变量声明属性,为IBOutlets自己的类声明属性以及在自己的类中使用访问器/变换器有什么好处?

Meh*_*ari 29

在iPhone世界中,没有可用的垃圾收集器.你必须通过引用计数仔细管理内存.考虑到这一点,请考虑以下区别:

name = @"Test";
Run Code Online (Sandbox Code Playgroud)

self.name = @"Test";
// which is equivalent to:
[self setName: @"Test"];
Run Code Online (Sandbox Code Playgroud)

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

基本概念不是iPhone特定的,但在没有垃圾收集器的环境中它变得至关重要.

  • 只是古玩,这也是现在我们有ARC的情况吗? (5认同)
  • 史蒂夫:我没见过导游.无论如何,如果你不使用属性并且你在任何地方*分配实例变量*,无论它是否在类中,你必须小心引用计数.除此之外,Mac OS X框架比iPhone同类产品更老.当iPhone SDK出现时,Objective-C 2.0已经存在,导致比OS X开发人员习惯使用更多的属性.总的来说,这主要是风格问题,而不是严格的规则. (3认同)
  • @meaning确实如此.但是当我写下答案时,它并没有. (2认同)

ste*_*anB 6

属性用于为实例变量生成访问器,没有任何魔法发生.

您可以手动实现相同的访问者.

你可以在Aaron Hillegass的书中找到成员变量的3个内存管理策略的例子.他们是assign/copy/retain.您可以根据给定变量的要求选择其中一个.

我假设您了解Objective-c中的内存管理...

访问者隐藏了每个变量的内存管理的复杂性和差异.

例如:

name = @"Test"
Run Code Online (Sandbox Code Playgroud)

是一个简单的任务,name现在持有参考NSString @"Test".但是你可以决定使用copyretain.无论您选择哪种版本的内存管理访问者隐藏了复杂性,您始终使用(或类似)访问变量:

[self setName:@"Test"] 
[self name]
Run Code Online (Sandbox Code Playgroud)

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

我的猜测是iPhone教程使用属性使新开发人员更容易跳过内存管理(即使用属性生成适当的访问器而不是每次手动实现它们都很方便).