iOS:屬性、修飾詞(內存管理) 及其對應成員變量 、ARC


------------早期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在CODE上查看代碼片派生到個人代碼片

  1. @interface UIViewController (UINavigationControllerItem)  

  2. @property(nonatomic,readonly,retainUINavigationItem *navigationItem;  

  3. @property(nonatomicBOOL hidesBottomBarWhenPushed;  

  4. @property(nonatomic,readonly,retainUINavigationController *navigationController;  

  5. @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在CODE上查看代碼片派生到個人代碼片

  1. @property(nonatomic,readonly)NSString *myName; //在.h 中  

  2. self.myName = @"ss"; 不能用;而 _myName = @"ss" 能用   //在.m中  

  3. //re-declare the property in a class extension  

  4. @interface ViewController ()    

  5. @property(nonatomic,readwrite)NSString *myName;  

  6. @end   

  7. 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. // 1,當把語義特性聲明爲assign時,setter和getter時方法內部實現  

  2. - (void)setName:(NSString *)name{  

  3.   _name = name;  

  4. }  

  5. - (NSString *)name{  

  6.  return _name;  

  7. }  

  8. //2,當把語義特性聲明爲retain時,setter和getter方法內部實現  

  9. - (void)setName:(NSString *)name{  

  10. if (_name != name) {  

  11. [ _name release];  

  12. _name = [name retain];  

  13. }  

  14. }  

  15. - (NSString *)name{  

  16. return [[ _name retain] autorelease];  

  17. }  

  18. //3,當把語義特性聲明爲copy時,setter和getter方法內部實現  

  19. - (void)setName:(NSString *)name{  

  20. if (_name != name) {  

  21. [ _name release];  

  22. _name = [name copy];  

  23. }  

  24. }  

  25. - (NSString *)name{  

  26. return [[ _name retain] autorelease];  

  27. }  

      注意自定setter方法的書寫,之前爲了「安全」都在releae後面賦了一個nil的值。這樣寫是錯誤的,尤爲對於retain的語音,由於有可能別的對象retain的它持有的對象,結果值被置爲nil了。另不用擔憂初始的時候_name 就release了一次,由於類的成員中對象的初始值都是nil。

[html] view plaincopy

  1. if (_name != name) {  

  2. [ _name release];  

  3.  _name = nil;  

  4.  _name = [name retain];  

  5. }  

  6. }  

相關文章
相關標籤/搜索