@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];
}
});