2013-10-29 62 views
0

假设我有一个属性myPropertyName,在我的类MyClassName中定义。手动内存管理在本文中使用。哪一个是初始化的,属性或其实例变量

MyClassName.h

#import <UIKit/UIKit.h> 
@interface MyClassName : NSObject { 
    @private 
     NSObject* myPropertyName; 
    @public 
} 
@property (nonatomic, retain) NSObject* myPropertyName; 
// Some methods prototypes are here 
@end 

MyClassName.m

#import "MyClassName.h" 
@implementation MyClassName 
@synthesize myPropertyName; 
// Some methods are here 
@end 

我很困惑与用途,例如myPropertyName声明,它的实例变量之间的差异的地方。例如,这三个初始化代码声明之间有什么区别,例如,在我的类myClassName的定制-(void)init方法中。

  1. self.myPropertyName = [[[NSObject alloc] init] autorelease];

    这一个呼唤myPropertyName二传手,但我不知道什么是实例变量存在的二传手使用的名称,myPropertyName(因为我已经宣布@private场命名为myPropertyName)或_myPropertyName(人们说这个带有underbar的是默认的)?

  2. myPropertyName = [[NSObject alloc] init];

    这是否初始化myPropertyName属性的实例变量?如果我没有@synthesize myPropertyName = _myPropertyName;,那么它是错误的,因为该属性的默认实例变量被称为_myPropertyName

  3. _myPropertyName = [[NSObject alloc] init];

    _myPropertyName还宣布为我的财产的实例变量myPropertyName即使我使用@synthesize myPropertyName;@private NSObject* myPropertyName;

在我的理解,物业只是一个名称(如myPropertyName),应该有封装在代码中的实际操作,如分配值所使用的一些实例变量。

+3

你不必再'@ synthesize'。关于什么似乎是你真正的问题,你可以有一个'@财产'没有相应的'伊娃'。 – nhgrif

回答

2

首先,我强烈推荐阅读Apple's documentation on properties,也由nhgrif链接。不过,我知道文档可能有点密集(尽管苹果公司的,我发现,并不是那么糟糕),所以我会在这里简要介绍一下属性。

我喜欢这个例子,所以我会用更新的形式重写你的两个类。

MyClassName.h

#import <UIKit/UIKit.h> 
@interface MyClassName : NSObject 

@property (nonatomic, strong) NSObject *myPropertyName; 
// method prototypes here 
@end 

MyClassName.m

#import "MyClassName.h" 
@implementation MyClassName 
// some methods here 
@end 

MyClassName现在有一个叫做NSObject *类型的myPropertyName财产。在这个例子中,编译器会为你“免费”做很多工作。具体来说,它将生成一个备份变量,并且还为myPropertyName生成一个setter和getter。如果我要重写这两个文件,并假装我的编译器,包括这些东西,他们应该是这样的:

MyClassName.h

#import <UIKit/UIKit.h> 
@interface MyClassName : NSObject { 
    NSObject *_myPropertyName; 
} 

@property (nonatomic, strong) NSObject *myPropertyName; 

- (void)setMyPropertyName:(NSObject *)obj; 
- (NSObject *)myPropertyName; 

@end 

MyClassName.m

#import "MyClassName.h" 
@implementation MyClassName 

- (void)setMyPropertyName:(NSObject *)obj 
{ 
    _myPropertyName = obj; 
} 

- (NSObject *)myPropertyName 
{ 
    return _myPropertyName; 
} 

@end 

再一次,所有这些都是为了“免费”而发生的:我只是向你展示发生了什么。现在为你的数字问题。

  1. 所有的

    self.myPropertyName = [[[NSObject alloc] init] autorelease];

    首先,你或许应该使用自动引用计数,或ARC。如果你是,你将不会被允许拨打autorelease。忽略那部分,这工作正常。不包括autorelease,这完全等价于:

    [self setMyPropertyName:[[NSObject alloc] init]];

    其中,如果你看一下第二个.m文件我写出来,上面基本上会转化为:

    `_myPropertyName = [[NSObject中的alloc]初始化]

  2. myPropertyName = [[NSObject alloc] init];

    书面,该代码会给出一个编译器错误,因为没有这个班叫myPropertyName变量。如果你真的想要访问的实例变量底层(或“后盾”)的myPropertyName属性,您可以通过使用其真实姓名:

    _myPropertyName = [[NSObject alloc] init]; // note the underscore

    但大部分的时间,最好是使用如第1点中所述,因为这允许副作用,以及键值编码和其他好东西。

  3. _myPropertyName = [[NSObject alloc] init];

    哦。那么你明白了。看点2

你提到:

我很困惑与用途,例如myPropertyName声明,它的实例变量之间的差异的地方。例如,这三个初始化代码声明之间有什么区别,例如,在我的类myClassName的定制-(void)init方法中。

如果没有明确说明,属性就是抽象概念;其数据存储在通常由编译器分配的普通实例变量中。它的访问权限通常应限制在设置者和获取者之中,除了重要的例外。为了保持这个答案的简短,我不会再详细说明这个问题。

还有一件事:作为nhgrif提到,你不需要再使用@synthesize关键字。编译器现在已经隐含地理解了这一点。

如果您对此不确定,发表评论或者,最好是阅读docs

+0

To @Riley,在你的这句话中*“正如所写,这段代码会给编译器一个错误,因为在这个类中没有变量叫做_myPropertyName,如果你真的想访问底层实例变量(或者”backing“), myPropertyName属性,你可以通过使用它的真实姓名。“*你是否确实意味着”这个类中没有名为** myPropertyName **的变量“? – Cong

+0

@conglu我确实。非常感谢您指出这一点。我的回答已被编辑。 – ravron

1

让我们这个例子:

@property NSString *fullName; 

如果实施,我们覆盖了getter和setter方法,在这些getter和setter方法,我们不使用的实例变量fullName,这是从来没有建立。例如:

- (NSString *)fullName 
{ 
    return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName]; 
} 

- (void)setFullName:(NSString *)fullName 
{ 
    //logic to split fullName into two strings 
    //self.firstName = etc 
    //self.lastName = etc. 
} 

在该示例中,存在用于创建无fullName实例变量。

这是根据Apple's Official Documentation

但是,如果你不同时覆盖setter和getter,创建一个实例变量。

作为旁注,您可以声明属性readonly,然后简单地覆盖getter(不使用变量)将会阻止创建ivar。同样,您可以声明一个属性writeonly并仅覆盖setter