转载地址:http://www.devdiv.com/ios_objective_c_property_instance_variable-blog-186016-51342.html
@synthesize name=_name;
先看下下面的代码,经常在别人的源码中看到:
@interface Person : NSObject
@property(nonamtic, retain) NSString *name;
@end
@implementatin Person
@synthesize name=_name;
@end
一直对@synthesize name=_name;这样的写法觉的很奇怪,这个_name是哪里来的?明明找不到它的定义,为什么编译器没报错?原来这个是系统生成的:
在64位系统中,系统会自动给类添加ivar(instance variable),添加的ivar以一个下划线“_”做前缀,即类似_ivar这样的格式。
但在32位系统中,如果类的@interface部分没有进行ivar声明,但有@property声明,在类的@implementation部分有相应的@synthesize,则会得到类似下面的编译错误:
Synthesize property ‘xxx’ must either be named the same as a compatible ivar or must explicitly name an ivar。(可惜找不到32位系统验证这个问题)
所以最好写成像下面这样:
@interface Person : NSObject{
NSString *_name;
}
@property(nonamtic, retain) NSString *name;
@end
@implementatin Person
@synthesize name=_name;
-(void)dealloc{
[_name release];
[super dealloc];
}
@end
1、这样做的原因之一就是不暴露实例的成员变量。
在这里简单说一下_name和name的区别。_name是Person类的成员变量,name是属性。
属性是用self.name,通过getter方法来调用的,可以在类外使用。
而成员变量是通过_name来调用,只能在该类对应的implementation中使用,在类外不能使用。
在类内方法访问成员变量时就应该直接使用成员变量,即带下划线的名字_name,类内方法不推荐使用self.name,因为使用存取器本来就是对外的,在内部使用可能会造成一些不必要的错误,比如:
self.name= [[NSString alloc] init]; //retain count为2,处理不好易导致内存泄露。
2、这样的写法还能避免一些奇怪的问题
property和synthesize定义了一对getter和setter方法,在这里的getter方法是name,setter方法是setName,事实上getter和setter方法操作的是变量_name。
如果是@synthesize name=_name;其getter方法为:
-(MyObject *)name
{
return _name;
}
如果是@synthesize name;其getter方法为:
-(MyObject *)name
{
return name;
}
当函数名和属性名重名的时候会出现未知的错误,为了避免这种情况,Apple的源码范例里面多数也采用@synthesize name=_name;这种方式。
在《Learn Objective-C on the Mac》中有这么一段话:
编译器和苹果公司都以下划线开头的形式保存实例变量名称,如果你尝试在其他地方使用下划线,可能出现严重的错误。这条规则不是强制性的,但是如果不遵守它,你可能会遇到某种风
险。