好的,以前一定要问过,但我看起来很生气,一无所获:
我的iphone应用程序中有一个简单的数组,我这样定义:
@property (nonatomic, strong) NSArray *pages;
@synthesize pages = _pages;
我在Apples示例代码中看到了这一点,并认为这是编写self.pages(即_pages替换self.pages)的一个很好的捷径,如下所示:
_pages = [[NSArray alloc] init];
然后Apple再次出现这种情况(不完全像这样,但看起来好像他们不断交换):
self.pages = [NSKeyedUnarchiver unarchiveObjectWithData:contents];
最后:
[_pages release];
这完全让我感到困惑。 _pages和self.pages之间会有什么区别?
感谢您的帮助。
答案 0 :(得分:5)
_pages
是对象的 ivar 的名称。 pages
是不同的属性名称
因此,@synthesize pages = _pages;
最后告诉pages
是ivar _pages
的属性。
您将在初始化程序和dealloc方法中通过_pages
对ivar直接访问进行包围。其他地方,属性名称用于获取/设置其值。
答案 1 :(得分:2)
使用简单分配时:
_pages = ...
您只需设置实例变量。
使用属性分配时:
self.pages = ...
它调用由编译器(或由您定义)自动合成的方法,并且为了合成此方法,它检查属性的类型(保留,赋值,...)并写入代码以匹配此类属性。
答案 2 :(得分:2)
这种差异来自常见的命名和使用习惯。
实例变量和属性都引用同一个对象。命名的不同用于指出ivar(_pages
)和属性(pages
)之间的差异。
ivar由类的实例拥有,由它们来处理它的所有权操作(alloc,retain,release等)。通常,这些所有权操作都在init
和dealloc
。
另一方面,该属性为ivar提供“指定”接入点。属性方法(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;
}
答案 3 :(得分:1)
_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
答案 4 :(得分:-1)
您可以将@synthesized
属性引用为instanceVariableName
或self.propertyName
。这两个名字可以相同或不同。
当您引用instanceVariableName
并修改该值时,不会应用关联属性的保留/复制逻辑 - 您只是引用“原始”变量。当您引用self.propertyName
时,应用了保留/复制逻辑 ,例如,如果使用“retain”声明属性,则旧值将为释放并保留新值。
将已保留的值(例如alloc / init中的值)分配给属性时,更简单(如果这是属性以前为nil
的初始化)要分配给instanceVariableName
和跳过需要release
的值(以便在操作结束时retains
的净数为1)。但是,在为属性分配不是retained
(autoreleased
retain
除外)的值时,您希望发生属性retain
,因此您可以使用self.propertyName
符号。
对于也是属性的实例变量使用前导“_”是一个简单的约定,以保持这两者分开,并避免意外地引用一个(通过错误地添加/删除self
)