Objective-C—— @Property詳解

來源:互聯網
上載者:User

標籤:

執行個體變數:
屬性其實說直白點就是 ivar + setter + getter(執行個體變數+存取方法),不過在OC中屬性多了字面量這一系列特殊關鍵字使得OC屬性有些不同。

成員屬性我們應該都使用過,比如現在定義一個Car類有name和speed成員變數:

#import <Foundation/Foundation.h>@interface Car : NSObject{    @public    NSString *name;    NSInteger speed;}@end

在OC類的內部有一個位移量,專門標記成員變數在記憶體中的所在位置。如果現在在添加一個新的成員變數在name的前面,那麼就會出現位移量整體便宜的問題,現在添加一個price執行個體:

#import <Foundation/Foundation.h>@interface Car : NSObject{    @public    NSInteger price;    NSString *name;    NSInteger speed;}@end

此時位移量在記憶體中顯示如下:

Car Car
name price
speed name
  speed

 

 

 

 

可以看到執行個體位移量發生了改變,但是OC將執行個體變數作為一種儲存位移量所用的“特殊變數”,交個類對象(class object)保管,位移量會在運行時尋找,所以總能正確的找到位移量。

 

@Property

使用屬性相比成員變數更加抽象,能夠使用setter和getter對變數做更多的處理。

說一下屬性的特性

 

@synthesize關鍵字

該關鍵字指定了屬性的執行個體變數名稱,並且根據儲存語義(readwrite、readonly)系統自動合成setter和getter方法,當然也可以手寫來覆蓋系統提供的。

@dynamic

該關鍵字告訴編譯器不要為我合成setter和getter方法,這些方法將由我自己實現。當然我們可以不實現這在編譯階段不會出現問題,直到運行時才會檢查是否實現了setter和getter,如果沒有實現就會拋出異常。

例如在CoreData中NSManagedObject子類的所有屬性全部都是dynamic標記的,這是因為子類的某些屬性不是

 

屬性特性(語義)

屬性的特質分為四類:

1.原子性:

  原子性就是指該屬性是否為同步的,OC中大部分屬性都是nonatomic(非原子性)的,如果不寫nonatomic那麼就會是原子性的。理論上來說原子性屬性的讀寫都將會是同步的,但是OC中atomic並不能一定確定屬性為同步的,如果真要進行同步操作,還要用更加深層次的同步鎖API。而且atomic會很影響效率,所以一般都會寫nonatomic。

2.讀/寫入權限:

  讀寫為readonly和readwrite兩種,前一種在系統只會合成getter方法,而後一種則會同時產生setter和getter。如果屬性設定為了readonly屬性,那麼該屬性是不可以修改的。

3.記憶體管理語義:

  assign:該方法只會針對“純量類型”(CGFloat或NSInteger等)的簡單賦值操作,id類型也要用assign,所以一般iOS中的代理delegate屬性都會用assign來標示,如:

@property (nonatomic, assign)   id <UITableViewDataSource> dataSource;@property (nonatomic, assign)   id <UITableViewDelegate>   delegate;

  strong: 使用該特性執行個體變數在賦值時,會釋放舊值同時設定新值,對對象產生一個強引用,用MRC來說就是引用計數+1。

  weak: 屬性工作表明了一種”非擁有關係“,既不釋放舊值,也不保留新值。用MRC就是引用計數不變,當指向的對象被釋放時,該屬性自動被設定為nil。這裡多說一點,weak的runtime實現是通過hash表完成的,用變數名做鍵,一旦發現屬性所指的對象被釋放了,立刻設定為nil。

  unsafe_unretained:和weak一樣,唯一的區別就是當對象被釋放後,該屬性不會被設定為nil。所以是unsafe的。

  copy:和strong類似,不過該屬性會被複製一個新的副本。很多時使用copy是為了方式Mutable(可變類型)在我們不知道的情況下修改了屬性值,而用copy可以產生一個不可變的副本防止被修改。如果我們自己實現setter方法的話,需要手動copy。

4.方法名:

  getter = <name>

  setter = <name>

  方法名可以修改為我們合成的方法名,可以使存取方法語義更加符合應用情境。

  如果要在其它屬性裡面設定屬性的話,還是要符合屬性特性,比如copy的話我們還是要手動copy一下屬性。這裡說一下構造方法裡需要直接操作執行個體變數,而不應該調用setter和getter。

 

對象內部盡量直接存取執行個體變數

首先說一下構造方法和析構方法中為什麼不能使用setter和getter,因為setter和getter是經過我們封裝過的方法,有可能增加一些判斷,而如果子類調用父類的構造方法同時實現了自己的setter和getter,那麼很可能就會出現問題。

通過屬性訪問執行個體變數會使用屬性的字面語義,會使用KVO所以在執行效率上肯定比直接調用執行個體變數慢,但是通過屬性訪問可以截獲屬性的擷取和設定更加方便調試和控制。

一般在類內部推薦設定用setter 擷取直接用執行個體變數。

這裡再說一下惰性載入,所謂惰性載入就是指,屬性會在第一次調用getter的時候初始化,如下:

-(NSString *)name{    if (!_name){        _name = [[NSString alloc] init];    }    return _name;}

那麼此時就只能夠通過getter來調用執行個體變數了。

 

Objective-C—— @Property詳解

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.