我们在进行iOS开发时,经常会在类的声明部分看见类似于 @synthesize window=_window;
的语句,那么,这个window
是什么,_ window
又是什么,两个东西分别怎么用,这是一个比较基本的问题,也关乎我们理解Objective-C中对类、类的属性、类的存取器、类的局部变量的统一理解。 在32位系统中,如果类的 @interface 部分没有进行 ivar 声明,但有 @property
声明,在类的@implementation
部分有响应的 @synthesize
,则会得到类似下面的编译错误:
Synthesized property ‘xX’ must either be named the same as a compatible ivar or must explicitly name an ivar
在 64-bit时,运行时系统会自动给类添加 ivar,添加的 ivar 以一个下划线”_”做前缀。 上面声明部分的 @synthesize window=_window;
意思是说,window
属性为_window
实例变量合成访问器方法。 也就是说,window
属性生成存取方法是setWindow
,这个setWindow
方法就是_window
变量的存取方法,它操作的就是_window
这个变量。通过这个看似是赋值的这样一个操作,我们可以在@synthesize
中定义与变量名不相同的getter
和setter
的命名,籍此来保护变量不会被不恰当的访问。 下面是一个常见的例子
写法一:
@interface MyClass:NSObject{
MyObjecct *_myObject;
}
@property (nonamtic, retain) MyObjecct *myObject;
@end
@implementatin MyClass
@synthesize myObject = _myObject;
@end
写法二:
@interface MyClass:NSObject
@property (nonamtic, retain) MyObjecct *myObject;
@end
@implementatin MyClass
@synthesize myObject = _myObject;
@end
这个类中声明了一个变量_myObject
,又声明了一个属性叫myObject
,然后用@synthesize
生成了属性myObject的存取方法,这个存取方法的名字应该是:setmyObject
和getmyObject
。@synthesize myObject=_myObject
的含义就是属性myObject
的存取方法是做用于_myObject
这个变量的。这种用法在Apple的Sample Code中很常见。
弄明白了这个语句的意思之后,我们也就清楚了myObject
和_myObject
的区别,那么,在使用的时候,有什么需要注意的地方,大家应该也都清楚了。是的,myObject
是属性,而_myObject
才是变量,我们最终操作的变量都是myObject
。 那么,同样是存取操作,语句
self.nameVarPtr = [[ObjectName alloc] init]
nameVarPtr = [[ObjectName alloc] init]
两种赋值方式的区别何在呢?
self.nameVarPtr = xxx
这种赋值方式等价于调用[self setnameVarPtr:xxx]
, 而setnameVarPtr:xxx
的方法的实现又是依赖于@property的属性的,比如retain,assign等属性。
nameVarPtr = xxx
的赋值方式,仅仅是对一个指针进行赋值。nameVarPtr
仅仅是一个指针变量,记录了xxx
的地址。在这个过程中不会调用setter方法,不会调用setter方法,就和@property没有关系,从而,也和retain,assign等属性没有关系。这种赋值方式就是一个简单的指针赋值。
综上,对成员变量进行赋值,为防内存泄露需要注意的点:
//1.self调用setter方法的方式
ObjectName* tmp= [[ObjectName alloc] init];
self.nameVarPtr =tmp; //retainCount=2
[tmp release]; //retainCount=1
//2.指针赋值方式,不会调用setter方法
nameVarPtr= [[ObjectName alloc] init]; // retainCount=1
所以,笔者建议大家在对某个变量进行赋值操作的时候,尽量要写self.myObj = xxx;
这才是最可靠的方法。