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等)。 通常,这些所有权操作在init
和dealloc
。
另一方面,该物业为伊瓦尔提供了“指定”接入点。 属性方法(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方法pages
和setPages:
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
属性引用为instanceVariableName
或self.propertyName
。 这两个名称可以相同或不同。
当您引用为instanceVariableName
并修改该值时,不会应用关联属性的任何保留/复制逻辑 – 您只是引用“原始”变量。 当您引用self.propertyName
,将应用保留/复制逻辑,例如,如果使用“retain”声明属性,则将释放旧值并保留新值。
将已保留的值(例如alloc / init中的值)分配给属性时,更简单(如果这是属性先前为nil
的初始化)分配给instanceVariableName
并跳过需要release
值(以便在操作结束时, retains
净数量将为1)。 但是,当将未retained
的值( autoreleased
retain
除外)分配给属性时,您希望retain
属性的retain
,因此您将使用self.propertyName
表示法。
对于也是属性的实例变量使用前导“_”是一个简单的约定,以保持这两者分开,并避免在意味着另一个时意外引用一个(通过错误地添加/删除self
)。