@property @synthesize @dynamic @synchronized
当你定义了一系列的变量时,需要写很多的getter和setter方法,而且它们的形式都是差不多的,,所以Xcode提供了@property和@synthesize属性,@property用在 .h 头文件中用作声明,@synthesize、@dynamic用在.m 文件中用于实现。
@property 在头文件中声明getter和setter方法
@synthesize 在实现文件中生成相应的getter和setter方法
@dynamic 告诉编译器,属性的setter与getter方法由用户自己实现,不自动生成。(假如一个属性被声明为@dynamic var,然后你没有提供@setter方法和@getter方法,编译的时候没问题,但是当程序运行到instance.var =someVar,由于缺setter方法会导致程序崩溃;或者当运行到 someVar = var时,由于缺getter方法同样会导致崩溃)
以上为旧版本的Xcode的一些特性。在最新的版本中这些关键字的功能有所不同。
1、如果在头文件中使用了@property关键字,则编译器除了声明变量的getter和setter方法之外,还会增加一个_var的成员变量,并且会在.m文件中实现相应的getter和setter方法(设值和取值方法)。
2、@synthesize这个属性可以不用
在使用oc进行开发时,经常需要对大量的成员变量生成设值方法和取值方法,如果全部手动实现,那么将浪费程序员大量的时间敲写这些重复性的垃圾代码。自从oc2.0开始,可以自动生成设值和取值方法。那就是使用@property属性和@synthesize关键字。关于这两个关键字使用中的细节在这里进行详细的解释。
1. 使用@property自动生成成员变量以及取值和设值方法
代码如下:
@interface Person:NSObject
@property int age;
@end
@implementation Person
@end
解释:例如这种在实现部分不使用@synthesize,直接使用@property属性进行声明,那么编译器会自动生成一个int _age;型的成员变量,而且会在实现部分自动生成如下的设值和取值方法。
- (void)setAge:(int)age
{ _age = age; }
- (int)age
{ return _age; }
2. 手动实现设值方法,使用@property自动生成成员变量和取值方法
代码如下:
@interface Person:NSObject
@property int age;
- (void)setAge:(int)age;
@end
@implementation Person
- (void)setAge:(int)age
{ _age = age; }
@end
解释:例如这种在实现部分不使用@synthesize,直接使用@property属性进行声明,并且实现部分手动生成了设值setAge:方法,那么编译器会自动生成一个int _age;型的成员变量,而且会在实现部分自动生成如下的取值方法。
- (int)age { return _age; }
同理,在实现部分不使用@synthesize,直接使用@property属性进行声明,并且实现部分手动生成了取值age:方法,那么编译器会自动生成一个int _age;型的成员变量,而且会在实现部分自动生成setAge:的设值方法。
3. 手动实现设值和取值方法,使用@property不会自动生成成员变量
代码如下:
@interface Person:NSObject
{ int _age; //此处必须手动实现 }
@property int age;
- (void)setAge:(int)age;
- (int)age;
@end
@implementation Person
- (void)setAge:(int)age { _age = age; }
- (int)age { return _age; }
@end
解释:例如这种手动实现设值和取值方法,那么即使使用了@property属性,那么编译器也不会自动生成一个int _age型的成员变量,必须自己手动声明一个_age的成员变量。如果不手动声明,那么编译器就会报错,因为设值和取值方法找不到_age的成员变量。
4. @synthesize的使用
代码如下:
@interface Person:NSObject
{ int _age;
int age;
}
@property int age;
@end
@implementation Person
@synthesize age;
@end
解释:
这种使用了@synthesize age;的情况,那么设置和取值方法会默认访问age成员变量,而不是_age成员变量,如果没有声明age的成员变量,那么设置和取值方法才会访问_age的成员变量。
如果想让设置和取值方法访问_age的成员变量,那么必须显示指明,即使用@synthesize age=_age,这样设置和取值方法就会访问_age的成员变量,而不是age的成员变量。
例如@synthesize age=_age这种显示指明访问哪个成员变量的方式,如果没有声明_age的成员变量而声明了age的成员变量,那么编译器也不会访问age成员变量,编译器而是会自动生成一个_age的成员变量去访问。
总结
@property和@synthesize提高了开发者的效率,不用重复的去敲写垃圾代码。
在使用了@property的情况,若手动实现了设值方法,编译会自动生成取值方法;若手动实现了取值方法,编译会自动生成设置值法(若只手动实现其中一个,编译器还会自动生成相应的成员变量);若手动实现了设值和取值方法,编译不会自动生成不存在的成员变量。
@synthesize age=variablename,age是属性, variablename才是我们要访问的成员变量。
@synchronized 锁
@synchronized,代表这个方法加锁, 相当于不管哪一个线程(例如线程A),运行到这个方法时,都要检查有没有其它线程例如B正在用这个方法,有的话要等正在使用synchronized方法的线程B运行完这个方法后再运行此线程A,没有的话,直接运行。
代码如下:
//线程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized(obj){
[obj method1];
sleep(10);
}
});
//线程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(1);
@synchronized(obj){
[obj method2];
}
});