Objective-C:_variable

好吧,以前一定要问这个但是我看起来很生气,一无所获:

我在我的iPhone应用程序中有一个简单的数组,我这样定义:

@property (nonatomic, strong) NSArray *pages; @synthesize pages = _pages; 

我在Apples示例代码中看到了这一点,并认为这是编写self.pages(即_pages替换self.pages)的一个很好的捷径,如下所示:

 _pages = [[NSArray alloc] init]; 

但是苹果又有了这个(不完全像这样,但看起来好像他们一直在随意交换):

 self.pages = [NSKeyedUnarchiver unarchiveObjectWithData:contents]; 

最后:

 [_pages release]; 

这让我很困惑。 _pages和self.pages之间有什么区别?

谢谢你的帮助。

_pages是对象的ivar的名称。 pages是不同的属性名称。
所以,@ @synthesize pages = _pages; 最后告诉pages是ivar _pages的属性。

您将在初始化程序和dealloc方法中通过_pages直接访问ivar。 在其他任何地方,属性名称用于获取/设置其值。

使用简单分配时:

_pages = …

你只需设置实例变量。

使用属性分配时:

self.pages = …

它调用由编译器(或由您定义)自动合成的方法,并且为了合成此方法,它检查属性的类型(保留,赋值,…)并写入代码以匹配此类型的属性。

这种差异来自常见的命名和使用实践。

实例变量和属性都引用同一个对象。 命名的区别用于指出ivar( _pages )和属性( pages )之间的差异。

ivar由类的实例拥有,由它们来处理它的所有权操作(alloc,retain,release等)。 通常,这些所有权操作在initdealloc

另一方面,该物业为伊瓦尔提供了“指定”接入点。 属性方法(setter和getter)可以执行正确管理ivar所需的附加操作。 因此,即使在拥有对象中,也不建议直接访问ivar(作为使用模式)。 例如,setter可能是这样实现的:

 - (void) setPages:(NSArray *)newValue { [newValue retain]; // additional operations that you will miss if you use the ivar [someObject someUsefulOperationThatIsReallyNeeded]; [pages release]; _pages = newValue; } 

_pages是实例变量, pages是属性名称。 该属性通过getter和setter方法pagessetPages: object.pages相当于[object pages]或者你的例子`[self setPages:[NSKeyedUnarchiver unarchiveObjectWithData:contents]];

所以唯一的实际对象是实例变量_pages ,因此只有这可以是内存管理。

该属性和合成器代码实际上与此代码相同(实际上,可能有额外的代码用于内存管理和线程锁定

 @interface MyClass { ... NSArray *_pages } - (NSArray*)pages; - (void)setPages:(NSArray*)newValue; @end @implementation MyClass - (NSArray*)pages { return _pages; } - (void)setPages:(NSArray*)newValue { _pages = newValue; // Note in non ARC code there would be some memort managment here } @end 

您可以将@synthesized属性引用为instanceVariableNameself.propertyName 。 这两个名称可以相同或不同。

当您引用为instanceVariableName并修改该值时,不会应用关联属性的任何保留/复制逻辑 – 您只是引用“原始”变量。 当您引用self.propertyName ,将应用保留/复制逻辑,例如,如果使用“retain”声明属性,则将释放旧值并保留新值。

将已保留的值(例如alloc / init中的值)分配给属性时,更简单(如果这是属性先前为nil的初始化)分配给instanceVariableName并跳过需要release值(以便在操作结束时, retains净数量将为1)。 但是,当将未retained的值( autoreleased retain除外)分配给属性时,您希望retain属性的retain ,因此您将使用self.propertyName表示法。

对于也是属性的实例变量使用前导“_”是一个简单的约定,以保持这两者分开,并避免在意味着另一个时意外引用一个(通过错误地添加/删除self )。