如果我们在OC的类中定义一个变量,要使得外部可以修改访问这个变量,我们可以手动添加setter/getter方法来操作变量。
例如:
//in MyClass.h
@interface MyClass : NSObject{
NSString * _name;
}
- (void)setName:(NSString *)newName;
- (NSString *)name;
@end
//in MyClass.m
#import "MyClass.h"
@implementation MyClass
- (void)setName:(NSString *)newName{
if(_name != newName){
_name = nil;
_name = [newName copy];
}
}
- (NSString *)name{
return _name;
}
@end
但是,当变量的数量变得很多的时候,我们就需要写大量的setter/getter使得代码量大大增加
此时我们就可以使用@property来让编译器自动为我们生成setter/getter方法,具体如下:
//in .h
@interface MyClass : NSObject{
NSString * _name;
}
@property(nonatomic,copy)NSString * name;
@end
//in .m
@implementation MyClass
@synthesize name = _name;
@end
此时,编译器就会自动为我们合成_name的setter/getter方法了,在实际执行中,编译器还是会优先查找是否存在setter/getter方法,如果存在,就使用,否则,就自动根据@property后的关键字来生成setter/getter方法。
在Xcode 4.5之后的版本中,我们甚至可以这样写
//in .h
@interface MyClass : NSObject
@property(nonatomic,copy)NSString * name;
@end
//in .m
@implementation MyClass
@end
编译器会自动帮我们添加名为_name的变量并为我们生成setter/getter方法。因此在实现中使用name变量时我们要么self.name要么_name,因为编译器为我们生成的变量名是_name而不是name。
@property后可跟关键字用以告诉编译器要生成的setter/getter方法的行为。
@property后可跟的关键字有
1.读写特性:readonly、readwrite
意义非常简单,就是只读、读写(默认为readwrite)
2.setter语义:assign、retain、copy(MRC默认assign)
assign:简单赋值
-(void)setName:(NSString *)newName{
_name = newName;
}
使用该语义不会对引用计数进行更改,因此对指针类型的OC对象使用该语义可能会因为所指之物被提前释放
通常对C/C++中基本变量类型,或结构体使用该语义
retain:新对象引用计数+1,旧对象-1
类似于下面的操作
-(void)setName:(NSString *)newName{
if(_name != newName){
_name = nil; //ARC
//MRC [_name release];
_name = [newName retain];
}
}
copy:创建一个新的引用计数为1的对象,使用copy方法赋值,旧对象release
-(void)setName:(NSString *)newName{
if(_name != newName){
_name = nil; //ARC
//MRC [_name release];
_name = [newName copy];
}
}
使用该特性需要类遵守NSCopying协议
3.所有者特性strong、weak(ARC默认strong)
strong:强引用,决定一个对象是否被回收,如果不存在指向一个对象的强引用,那么该对象就会被回收,否则就不会被回收(可能造成循环引用而产生内存泄漏)
weak:若引用,若引用不决定对象是否被回收,即便有很多若引用指向一个对象,但是没有强引用指向这个对象,这个对象也会被回收。若引用指向的对象被回收后,指针被置为nil(向nil发送任何消息都不会造成运行时崩溃)
weak常用于delegate。
4.原子特性atomic、nonatomic(默认atomic)
atomic:原子性,指的是一个操作不可再分割,例如在对一个变量set的时候,就不允许get,直到set完毕。通常使用该特性来保证线程安全
nonatomic:非原子性,原子性操作为了保证线程安全,会有额外的性能消耗,当我们肯定一个变量的存取不存在线程安全问题后,我们可以使用nonatomic来提升存取效率。
使用atomic并不能完全保证线程安全,要保证线程安全还是需要同步和互斥机制