------------早期GCC版本------------html
--@property A做用就是讓編譯器在h文件聲明A 的setter/getter方法;ios
--@synthesize A做用就是讓編譯器在m文件生成A 的setter/getter方法;(若是本身實現了setter/getter方法,則以本身實現爲準)編程
--要求必需要成員變量A 對應屬性;或者將名稱不同成員變量_A對應屬性A,即@synthesize A = _A; 安全
--另外,屬性的retain、assign、copy等修飾詞就是在setter方法裏retain/release等額外操做;多線程
------------如今LLVM版本------------併發
--@property A做用強大了,除了原有做用;同時還Default synthesis of @property instance variables and accessor methods;具體:ide
1..若是發現m中沒有@synthesize,則"Autosynthesized A= _A"(補上synthesize和匹配的_A);有@synthesize,不作處理;性能
2.根據m中@synthesize中匹配的實例變量查看有沒有,若沒有建立之。(@synthesize A匹配的實例變量爲A;@synthesize A = _A 匹配的實例變量爲_A)atom
--上敘倆規則根據例子總結,未找到相關文檔說明:spa
--例子1;只有@property A ;那麼m中 _A 能用,A 不能用;
--例子2;有@property A + 成員變量A; 那麼 _A 能用,A能用;
--例子2: 有@property A + @synthesize A;那麼 _A 不能,A 能用;
--例子3;有@property A + @synthesize A + 成員變量_A;那麼 _A 能用,A 都能用;
--例子4;有@property A + @synthesize A=_A + 成員變量_A; 那麼 _A 能用,A 不能用;
--一個經典例子,類中有屬性@property(nonatomic,strong)IBOutlet UIButton *aButton; 和成員變量IBOutlet UIButton *_aButton; 沒有@synthesize;他倆分別關聯button1,和button2,運行程序,無論是self.aButton 仍是_aButton都是指向button1;說明@property在編譯的時候起做用,將_aButton 和屬性aButton關聯爲一個。若是屬性和成員變量是同樣的,則一個關聯button1,另外一個也關聯了。
------------類別中的屬性property ------------
--類與類別中添加的屬性要區分開來,由於類別中只能添加方法,不能添加實例變量。常常會在ios的代碼中看到在類別中添加屬性,這種狀況下,是不會自動生成實例變量的。例:UINavigationController.h中會對UIViewController類進行擴展
[objc] view plaincopy
@interface UIViewController (UINavigationControllerItem)
@property(nonatomic,readonly,retain) UINavigationItem *navigationItem;
@property(nonatomic) BOOL hidesBottomBarWhenPushed;
@property(nonatomic,readonly,retain) UINavigationController *navigationController;
@end
這裏添加的屬性,不會自動生成實例變量,這裏添加的屬性實際上是添加的getter與setter方法。
注意一點,匿名類別(匿名擴展)是能夠添加實例變量的,非匿名類別是不能添加實例變量的,只能添加方法,或者屬性(其實也是方法)
============修飾詞============
主要分爲三類:
1.原子性(Atomicity)包含:nonatomic;
2.讀寫屬性(Writability)包含:readwrite / readonly;
3.setter語義(Setter Semantics)包含:assign / retain / copy;
------原子性:
nonatomic:非原子性訪問,不加同步,多線程併發訪問會提升性能。若是不加此屬性,則默認是兩個訪問方法都爲原子型事務訪問。默認值是atomic,爲原子操做。(atomic是Objc使用的一種線程保護技術,基本上來說,是防止在寫未完成的時候被另一個線程讀取,形成數據錯誤。而這種機制是耗費系統資源的,因此在iPhone這種小型設備上,若是沒有使用多線程間的通信編程,那麼nonatomic是一個很是好的選擇。)
------讀寫屬性:
readwrite / readonly:決定是否生成set訪問器,readwrite是默認屬性,生成getter和setter方法;readonly只生成getter方法,不生成setter方法。readonly關鍵字表明setter不會被生成, 因此它不能夠和 copy/retain/assign組合使用。
注意:readwrite/readonly配合使用:屬性在外部是隻讀,本身使用時讀寫-->re-declare the property in a class extension
[objc] view plaincopy
@property(nonatomic,readonly)NSString *myName; //在.h 中
self.myName = @"ss"; 不能用;而 _myName = @"ss" 能用 //在.m中
//re-declare the property in a class extension
@interface ViewController ()
@property(nonatomic,readwrite)NSString *myName;
@end
self.myName = @"ss"; 和 _myName = @"ss" 都能用
------setter語義:
這些屬性用於指定set訪問器的語義,也就是說,這些屬性決定了以何種方式對數據成員賦予新值。
--assign:直接賦值,索引計數不改變,適用於簡單數據類型,例如:NSIngeter、CGFloat、int、char等。
--retain:指針的拷貝,使用的是原來的內存空間。對象的索引計數加1。此屬性只能用於Objective-C對象類型,而不能用於Core Foundation對象。(緣由很明顯,retain會增長對象的引用計數,而基本數據類型或者Core Foundation對象都沒有引用計數)。
--copy:對象的拷貝,新申請一塊內存空間,並把原始內容複製到那片空間。新對象的索引計數爲1。此屬性只對那些實行了NSCopying協議的對象類型有效。
不少Objective-C中的object最好使用用retain,一些特別的object(例如:string)使用copy。
============自定義setter/getter方法============
[html] view plaincopy
// 1,當把語義特性聲明爲assign時,setter和getter時方法內部實現
- (void)setName:(NSString *)name{
_name = name;
}
- (NSString *)name{
return _name;
}
//2,當把語義特性聲明爲retain時,setter和getter方法內部實現
- (void)setName:(NSString *)name{
if (_name != name) {
[ _name release];
_name = [name retain];
}
}
- (NSString *)name{
return [[ _name retain] autorelease];
}
//3,當把語義特性聲明爲copy時,setter和getter方法內部實現
- (void)setName:(NSString *)name{
if (_name != name) {
[ _name release];
_name = [name copy];
}
}
- (NSString *)name{
return [[ _name retain] autorelease];
}
注意自定setter方法的書寫,之前爲了「安全」都在releae後面賦了一個nil的值。這樣寫是錯誤的,尤爲對於retain的語音,由於有可能別的對象retain的它持有的對象,結果值被置爲nil了。另不用擔憂初始的時候_name 就release了一次,由於類的成員中對象的初始值都是nil。
[html] view plaincopy
if (_name != name) {
[ _name release];
_name = nil;
_name = [name retain];
}
}