Objective-C 之 @property和@synthesize

   我用了不到一週的時間學習了Objective-C,後面的大部分時間我都在瞭解如何使用IOS的SDK和一些高級的話題,到目前已經有兩個多月的時間了。目前能作一些簡單的應用,可是在寫代碼的時候明顯感受到基礎不夠紮實,畢竟一週的時間只能對一門語言有個概覽。要想精通一門語言是遠遠不夠的。 html

   因此我把本身學習過程當中遇到的一些問題整理在博客上,這也是一個學習理解的過程。 安全

   今天要說的內容是Objective-C 中的 @property和@synthesize。在這以前先講講訪問器(Accessor),也就是咱們所知道的setter和getter方法。《Cocoa Design Patterns》中的將它歸類爲基礎模式中的一種。訪問器是很重要的技術,用來訪問和設置對象的實例變量(不是指對象自己,而是對象中的屬性)。有時候可能須要用不一樣的方式或者經過計算等方式來獲取或設置實例變量,訪問器給了咱們很大的靈活性。在Cocoa中訪問器有不少的優勢: 多線程

  • 實現靈活性。 能夠在訪問器中改變並實現不一樣的實例變量訪問方式而不影響其餘代碼。
  • 可維護性。經過訪問器對實例變量的更改易於維護。
  • 內存管理。訪問器方法提供了簡單的方法去遵照Cocoa的約定把內存管理代碼隔離在少部分代碼中。
  • 支持KVC和KVO。 KVC和KVO是很強大的技術。可是它們依賴於正確命名訪問器。

     下面這段代碼簡單的實現了一個訪問器(setter和getter): app

//setter
-(void)setStuName:(NSString *)stuName
  {  //_stuName 是實例變量
     if (_stuName != stuName)
     {
        [_stuName release];
         _stuName = [stuName copy];
     }
  }
//getter
  -(NSString *)stuName
  {
     return _stuName;
  }

    上面代碼中的setter中還涉及到必定的內存管理,既然這個技術這麼重要,那麼有沒有一種更方便的方法去作呢?答案就是@property和@synthesize。它們是Objective-C 2.0加入的指令,前者用於聲明,後者用於合成訪問器,結合使用就能夠自動生成訪問器了。 學習

    下面這段代碼使用@property和@synthesize: ui

@interface Student : NSObject
  
@property (nonatomic, copy) NSString *stuName;
@end

@implementation Student

@synthesize stuName = _stuName;
@end

   這段代碼的效果跟上面代碼的效果是同樣的,是否是很方便呢? atom

   使用@property和@synthesize很方便,但又給咱們帶來了不少疑問好比在上面的代碼中又出現了nonatomic和copy,是什麼意思?在@property中還有其餘幾個關鍵字,它們都是有特殊做用的,我把它們分爲三類分別是:原子性,訪問器控制,內存管理。 spa


    原子性 線程

    atomic(默認):atomic意爲操做是原子的,意味着只有一個線程訪問實例變量。atomic是線程安全的至少在當前的訪器上我是安全的。它是一個默認的,可是不多使用。它的比較慢,這跟ARM平臺和內部鎖機制有關。 code

    nonatomic: nonatomic跟atomic恰好相反。表示非原子的,能夠被多個線程訪問。它的速度比atomic快。但不能保證在多線程環境下的安全性,在單線程和明確只有一個線程訪問的狀況下普遍使用。

    訪問器控制

    readwrite(默認):readwrite是默認的,表示同時擁有setter和getter。

    readonly: readonly 表示只有getter沒有setter。

    有時候爲了語意更明確可能須要自定義訪問器的名字:

@property (nonatomic, setter = mySetter:,getter = myGetter ) NSString *name;
     最多見的是BOOL類型,好比標識View是否隱藏的屬性hidden。能夠這樣聲明

@property (nonatomic,getter = isHidden ) BOOL hidden;
     要注意修改setter或者getter的名字是存在反作用的,可能會使KVC和KVO沒法正常工做。

    內存管理

    retain:使用了retain意味着實例變量要獲取傳入參數的全部權。具體表如今setter中對實例變量先release而後將參數 retain以後傳給它。下面這段代碼展現了retain相似的行爲:

-(void)setStuName:(NSString *)stuName
  {
     if (_stuName != stuName)
     {
        [_stuName release];
         _stuName = [stuName retain];
     }
  }

    assign(默認):用於值類型,如int、float、double和NSInteger,CGFloat等表示單純的複製。還包括不存在全部權關係的對象,好比常見的delegate。

    strong:是在ARC伴隨IOS引入的時候引入的關鍵字是retain的一個可選的替代。表示實例變量對傳入的參數要有全部權關係即強引用。strong跟retain的意思相同併產生相同的代碼,可是語意上更好更能體現對象的關係。

    weak: weak跟assign的效果類似,不一樣的是weak在對象被回收以後自動設置爲nil。並且weak智能用在iOS 5或之後的版本,對於以前的版本,使用unsafe_unretained。

    unsafe_unretained:weak的低版本替代。  

    copy:copy是爲是實例變量保留一個本身的副本。


    如今明白了@property是怎麼回事了,可是@synthesize是怎麼回事,看看以前的第一段代碼:

@synthesize stuName = _stuName;
    這裏的stuName = _stuName是什麼意思?stuName是propertyName跟@property聲明的名字同樣。然後面的_stuName 是實例變量名。生成的訪問器就是來訪問的 _stuName的。代碼的樣子就和最開始那setter和getter代碼所描述的同樣。

    注意一個問題,咱們並無聲明_stuName這個變量,這是編譯器自動幫咱們建立的。 若是這段指令我換個寫法:@synthesize stuName = a;   而且咱們沒有在interface裏面聲明這個變量,那麼會自動建立一個變量a。

   若是這裏寫成這樣:

@synthesize stuName; //等同於 @synthesize stuName = stuName;

    在Xcode4.4中,Xcode添加的一些新的編譯特性其中一個就是默認合成(Default Synthesis)。默認合成就再也不須要顯示的使用@synthesize指令了,這很方便可是要注意的是,默認合成遵照的約定,這裏的也就是命名規則是propertyName = _propertyName。 

  下面一段代碼幫助理解:

//對於下面的@propety
@property (nonatomic, copy) NSString *stuName; 
//默認合成的規則是這樣:
@synthesize stuName = _stuName;

   以上是我所瞭解的@property和@synthesize,若是跟你的理解不一樣,或者有什麼錯誤,請給我留言:)。

相關文章
相關標籤/搜索