Objective-C:_variable

时间:2011-12-17 14:24:15

标签: iphone objective-c ios global-variables self

好的,以前一定要问过,但我看起来很生气,一无所获:

我的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之间会有什么区别?

感谢您的帮助。

5 个答案:

答案 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等)。通常,这些所有权操作都在initdealloc

中进行

另一方面,该属性为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属性引用为instanceVariableNameself.propertyName。这两个名字可以相同或不同。

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

将已保留的值(例如alloc / init中的值)分配给属性时,更简单(如果这是属性以前为nil的初始化)要分配给instanceVariableName和跳过需要release的值(以便在操作结束时retains的净数为1)。但是,在为属性分配不是retainedautoreleased retain除外)的值时,您希望发生属性retain,因此您可以使用self.propertyName符号。

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