iOS 屬性修飾符

@property 有兩個的作用:一是自動生成私有屬性(一般是下劃線+屬性名),而是自動生成 gettersetter 方法。
聲明屬性時,緊跟在 @property 之后的屬性修飾符則描述了自動生成 gettersetter 方法的規則。

根據MRC和ARC劃分屬性修飾符的使用范圍:
MRC:nonatomic,atomic,retain,assign,copy,readwrite,readonly
ARC:nonatomic,atomic,strong,weak,assign,copy,readwrite,readonly

  • nonatomic
    • nonatomic 表示非原子屬性
      • 并發訪問性能高,但是訪問不安全
        • 它直接訪問內存中的地址,不關心其他線程是否在改變這個值,并且中間沒有死鎖保護;所以可能拿不到完整的值
  • atomic
    • atomic 表示原子屬性
      • 系統生成的 getter/setter 會保證 get、set 操作的完整性,不受其他線程影響
        • 系統生成的 getter/setter 方法中,使用了 @synchronized(self)
        • 如果一個線程正在執行 getter/setter,其他線程就得等待
      • 如果有另一個線程同時在調 [property release],那可能就會crash,因為 release 不受 getter/setter 操作的限制。
        • 也就是說,atomic 修飾的屬性只能說是讀/寫安全的,但并不是線程安全的
          • 因為別的線程還能進行讀寫之外的其他操作。
          • 線程安全需要開發者自己來保證。
    • 系統默認的屬性是 atomic
  • strong
    • strong 表示對對象的強引用
      • 強引用時,引用計數會 +1
      • 給 strong 屬性賦值時,setter 方法中會先 release 舊值再 retain 新值并賦值
      • 兩個對象之間相互強引用會造成循環引用,內存泄漏
  • weak
    • weak 表示對象的弱引用
      • 弱引用時,不會使傳入的對象計數+1

      • 被其修飾的對象隨時可能被系統銷毀回收

        • 當該對象的引用計數為 0,則會被回收,對象被釋放以后,weak 指針會被自動設置為 nil

          在OC的運行時環境中,維護了一種 weak 表(哈希表)
          這張哈希表用對象的首地址作為 key,用 weak 指針自身的地址組成的數組作為 value
          當對象被釋放后,通過這個對象的起始地址來找到所有指向它的 weak 指針,并將它們指向nil

      • weak 多用于避免循環引用

  • assign
    • assign 主要用于修飾基本數據類型
      • 包括OC基本數據類型(NSInteger,CGFloat)和C數據類型(int, float, double, char)
    • 基本數據類型存儲在棧中,內存不用程序員管理。
    • assign 也可以修飾對象,但是當對象被釋放后,指針依然指向之前的內存地址。
      - 此時,訪問被釋放的地址就會 crash
      • 這個已經被釋放了的對象被稱為 僵尸對象
    • assign 在 MRC 和 ARC 下都可以使用
  • retain
    • 在 MRC 下使用,用于修飾對象
    • 被 retain 修飾的對象,retainCount要+1
    • retain 只能修飾 OC 對象,不能修飾非 OC 對象(如 Core Foundation 對象)
      • retain 會增加對象的引用計數,而基本數據類型或者 Core Foundation 對象都沒有引用計數
    • 賦值時,先 release 舊值,再 retain 新值
  • copy
    • copy 表示在賦值時使用傳入值的一份拷貝
      • 賦值時,創建了一個新的對象,并將傳入對象的值全部拷貝到新對象
      • 賦值后,新對象的 retainCount 為 1,而舊對象的 retainCount 不變
    • 只能修飾對象類型,不能修飾基礎數據類型
    • 用copy修飾的對象,必須實現
      NSCopying 協議,也就是實現方法 -(id)copyWithZone:(nullable NSZone *)zone
      • 系統自動生成的 setter 方法中會調用這個方法
      • 至于 copy 是深拷貝還是淺拷貝完全是看 copyWithZone 的實現方式,copy 修飾符和深拷貝、淺拷貝沒有關系
    • 一般用于修飾不可變的屬性(NSArray,NSDictionary,NSString,block)
      • 即使用 copy 修飾 NSMutableArray,將一個可變 NSMutableArray 賦值給 copy 修飾的屬性也會變成不可變數組 NSArray
        • 若 a 被 copy 修飾,則 a = b 等價于 a = [b copy]
      • 為什么要用 copy 修飾 NSString ?
        如果用 retain 修飾 NSString,
        當把 NSMutableString 賦值給 NSString 時,只是拷貝了指針;
        如果賦值后源字符串改變,這個屬性值也跟著改變。(不可控)
        如果用 copy 修飾 NSString,
        當把 NSMutableString 賦值給 NSString 時,會生成一份拷貝內容;
        即使賦值后源字符串改變,這個屬性值也不會改變。(保證了安全)
  • readwrite
    • readwrite 表示該屬性可讀可寫
    • 系統會自動創建 setter 和 getter 方法
    • readwrite 是默認的屬性修飾符
  • readonly
    • readonly 表示該屬性只可讀,不可寫
    • 只會生成get方法
    • 對用 readonly 修飾的屬性賦值時,編譯器會報錯提示:“Assignment to readonly property”。
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 一. 成員變量,實例變量,屬性變量成員變量 : 用在類的內部,無須與外部接觸.成員變量默認是被保護的,所以不會有s...
    Mccc_閱讀 2,137評論 0 8
  • iOS屬性問題 屬性修飾符的作用 iOS5之前是MRC, 內存需要程序員管理,iOS之后是ARC,除非特殊情況(例...
    自律_自強_通達閱讀 969評論 0 1
  • 前言 很多剛接觸iOS的朋友,對property的可選參數如何使用,什么情況下使用哪種選項不了解,也問了我很多這方...
    G_GUI閱讀 979評論 0 0
  • iOS開發中屬性修飾符基本上每天都會打交道,網上總結也很多,本文按照實際開發的角度簡單介紹一下屬性修飾符,屬性修飾...
    FlyElephant閱讀 2,305評論 0 4
  • 一.寫在前面的話 為什么要把他排在第一位?這是有原因的,因為這破玩意在開發中很少會引起注意,一般人都是一帶而過,不...
    objcat閱讀 371評論 0 3