IOS 關於property的詳細解法


1.格式

@property (參數1,參數2,...) 類型 名字; 

eg: @property(nonatomic,retain) UIWindow *window; 其中參數主要分為三類: • 讀寫屬性: (readwrite/readonly/setter = /getter = ) • setter語意:(assign/retain/copy) • 原⼦子性: (atomicity/nonatomic) • nullability annotations: (nonnull/nullable)

參數意義:

- readwrite 產生setter\getter⽅方法 - readonly 只產生簡單的getter,沒有setter, 默認的讀寫屬性 - setter 指定生成setter⽅法的名字 - getter 指定生成getter方法的名字 - assign 默認類型,setter方法直接賦值,而不進⾏retain操作,適⽤於基本數據類型, 對象類型, 不會發⽣生引用計數變化 - retain setter方法對參數進⾏行release舊值,再retain新值 - copy setter方法進⾏行Copy操作,與retain一樣 - atomic 保證多線程訪問下的安全,但浪費系統資源,原子性控制的默 認設置 - nonatomic 禁⽌多線程,變量保護,提高性能 - nonnull 表示對象可以是NULL或nil - nullable 表⽰對象不應該為空

2.重要屬性對比

  • <atomic> VS <nonatomic>
1.atomic 是默認的屬性,表示對象的操作屬於原子操作,主要是在多線程的環境下,提供多線程訪問的安全。 我們知道在多線程的下對對象的訪問都 需要先上鎖訪問后再解鎖,保證不會同時有⼏個操作針對同⼀個對象。 如果編程中不涉及到多線程,不建議使用,因為使用atomic⽐比nonatomic更耗費系統資源。 2.nonatomic 表⽰訪問器的訪問不是原⼦操作,不支持多線程訪問安全,但 是訪問性能⾼。
  • <readwrite> VS <readonly>
1.readwrite 是默認的屬性,表⽰可以對象進⾏讀和寫,自動生成setter和getter⽅法。 2.readonly 表示只允許讀取對象的值,只會生成對象的getter⽅法。 //以下等價 @property (nonatomic,retain) NSObject *object; @property (nonatomic,retain,readwrite) NSObject *object;
  • < retain >, < assign > VS < copy >
1.retain 表⽰示對NSObject和及其⼦子類對象release舊值,再retain新值,使對象的應⽤計數增加⼀。 該屬性只能使⽤用於obejective-c類型對象,不能用於Core Foundation對象。 2.assign 是默認屬性,只可以對基本數據類型(如CGFloat, NSInteger,Bool,int,代理對象)等使⽤。 該方式會對象直接賦值而不會進行retain操作。 3.copy 表⽰重新建立一個新的計數為1的對象,然后釋放掉舊的值。 都知道retain是對指針的拷⻉,copy是對內容的拷⻉。 eg:NSString 對象 的地址為0x100,其內容為“string” 如果使用copy到另外一個NSString對 象,則會⽣生成另外⼀個地址為0x110的對象,只不過內容仍然是’string“。 如果使用retain到另外一個NSString對象,則該對象的地址仍然為0x100,只不過 該對象的計數變為2.
retain 是指針拷貝
copy 是內容拷貝 //在拷貝之前,都會釋放舊的對象。 assign:簡單賦值,不更改索引計數(Reference Counting)。 copy :建立一個索引計數為1的對象,然后釋放舊對象 retain:釋放舊的對象,將舊對象的值賦予輸入對象,再提高輸入對象的輸入對象的索引計數為1
//事例說明 @property (nonatomic,retain) TestObject *object; @property (nonatomic,copy ) TestObject *object; /********** Getter等效代碼***********/ //.m中getter等效代碼 - (TestObject*)object{ return object; } //.m中getter等效代碼 - (TestObject*)object{ [object retain]; return [object autorelease];//用完立即釋放 } /********** Setter等效代碼分析***********/ - (void)setObject:(TestObject*)newObject{ if(object != newObject){ [object release]; object = [newObject copy]; } }
  • < strong > VS < weak >
  目的:對象聲明時需要加⼊入strong和weak,方便內存的自動管理。 ->strong:強引⽤用,默認的屬性,類似於retain,其實是一個相對的概念,就是一個引用。 默認的所有實例變量和局部變量都是strong指針。 如果有一個強引⽤持有該對象,則該對象就不能被釋放。 ->weak:弱引⽤,類似於assign,弱引用除了不決定對象的存亡外,其他與強引用相同。 即使一個對象被持有⽆數個若引用,只要沒有強引用指向他,那麽其還是會被清除,它不是對象的擁有者。 其值會在對象被釋放后自動設置為nil。 weak指針主要用於“父-子”關系,父親擁有⼀個⼉子的strong指針 因此父親是兒子的所有者;但為了阻止所有權循環,兒⼦需要使用weak指針指向父親。 eg:典型例⼦是delegate模式 ViewController通過strong指針(self.view)擁有⼀個UITableView的dataSource和delegate都是weak指針
  • < nonnull > VS < nullable >
1. swift:可以使⽤!和?來表⽰一個對象是optional的還是non- optional,如view?和view!。 2. Objective-C:沒有這一區分,view即可表示這個對象是optional,也可表示是non-optional。 說明:這樣就會造成一個問題: 在Swift與Objective-C混編時,Swift編譯器並不知道一個Objective-C對象到 底是optional還是non-optional,因此這種情況下編譯器會隱式地將Objective- C的對象當成是non-optional。  為了解決這個問題,蘋果在Xcode 6.3引⼊入了⼀個Objective-C的新特性: nullability annotations。這⼀新特性的核⼼心是兩個新的類型注釋:nullable 和nonnull。 ->nullable 表⽰對象可以是NULL或nil ->nonnull 表示對象不應該為空 說明:當我們不遵循這一規則時,編譯器就會給出警告。 在任何可以使用const關鍵字的地⽅都可以使⽤nullable和nonnull,不過這兩個關鍵字僅限於使用在指針類型上。 在⽅法的聲明中,我們還可以使用不帶下划線的nullable和nonnull //建議對象屬性不能為空,使用方式1 @property (nonatomic,copy,nonnull) NSArray *items;//方式1 @property (nonatomic,copy ) NSArray *items;//方式2

3.錯誤代碼屬性設置

錯誤1:

//錯誤寫法 @property (nonatomic) NSString *name; @property (nonatomic,assign) NSString *name//等價 //正確寫法 @property (nonatomic,copy ) NSString *name; 分析:不是基本數據類型的對象,所以默認的assign修飾符是不行的,由於atomic, readwrite,assign是默認,以下寫法是可行的: //正確寫法 @property NSInteger maxCount; @property (atomic,assign,readwrite) NSInteger maxCount;//等價

4.總結

說明:手動實現getter和setter方法(atomic/nonatomic/retain/ assign/copy定義的對象) 只是給編譯器的建議,編譯器首先會到代碼⾥里⾯去找。 1.如果定義了相應的getter和setter的方法,那么好,⽤手動定義的getter&&setter方法 2.如果沒有,編譯器就會根據對象自動生成相應的getter和setter方法

5.⭐️⭐️⭐️⭐️重點總結⭐️⭐️⭐️⭐️

重點!!!重點!!!重點!!!!

1.copy 使用類型 :NSString,block 2.assign使用類型 :delegate,int,float,NSInteger,bool,枚舉,結構體... 3.retain使用類型 :NSArray,NSDate 4.strong使用類型 :NSString/block以外的OC對象 5.weak 使用類型 :當2個對象相互引用,一端用strong,一端用weak; 6.readOnly :只讀時候(即只需要getter方法的時候); readWriete :默認屬性(getter&&setter方法)

6.補充

屬性中的修飾詞 - 我的理解 : ------------------------------------------------------------------------------ assign ( ARC/MRC ) 1.這個修飾詞是直接賦值的意思 , 整型/浮點型等數據類型都用這個詞修飾 . 2.如果沒有使用 weak strong retain copy 修飾 , 那么默認就是使用 assign 了. ( 它們之間是有你沒我的關系 ) 3.當然其實對象也可以用 assign 修飾 , 只是對象的計數器不會+1 . ( 與 strong 的區別 ) 4.如果用來修飾對象屬性 , 那么當對象被銷毀后指針是不會指向 nil 的 . 所以會出現野指針錯誤 . ( 與weak的區別 ) ------------------------------------------------------------------------------ weak ( ARC ) 1.弱指針是針對對象的修飾詞 , 就是說它不能修飾基本數據類型 . 2.weak 修飾的對象計數器不會+1 , 也就是直接賦值 . 3.弱引用是為打破循環引用而生的 . 4.它最被人所喜歡的原因是 它所指向的對象如果被銷毀 , 它會指向 nil . 而 nil 訪問什么鬼都不會報野指針錯誤 . ------------------------------------------------------------------------------ strong ( ARC ) 1.直接賦值並且計數器 +1 . 2.在 ARC 里替代了 retain 的作用 . ------------------------------------------------------------------------------ retain ( MRC ) 1.release 舊對象( 舊對象計數器 -1 ) , retain 新對象( 新對象計數器 +1 ) , 然后指向新對象 . 2.在set方法里面是這樣的 : if (_delegate) { [_delegate release]; } _delegate = [delegate retain]; ------------------------------------------------------------------------------ copy ( ARC/MRC ) 1.copy 在 MRC 時是這樣做的 release 舊對象( 舊對象計數器 -1 ) , copy 新對象( 新對象計數器 +1 ) , 然后指向新對象 . 1.1在set方法里面是這樣的 :  if (_delegate) {  [_delegate release];  }  _delegate = [delegate copy]; 2.copy 在 ARC 時是這么干的 copy 新對象( 新對象計數器 +1 ) , 然后指向新對象 . 2.1在set方法里面是這樣的 :  _delegate = [delegate copy]; 3.使用注意 : 3.1 修飾的屬性本身要不可變的 . 例如 NSMutableArray 采用 copy 修飾 , 添加元素表面上可以 一到運行就崩潰了 , 因為 copy 過后實際上成了NSArray了 . ( 隊友 , 我們不吭你 ) 3.2 遵守 NSCopying 協議的對象使用 . ------------------------------------------------------------------------------ nonatomic ( ARC/MRC ) 1.不對set方法加鎖 . 2.性能好 3.線程不安全 atomic ( ARC/MRC ) 1.原子屬性就是對生成的 set 方法加互斥鎖 @synchronized(鎖對象) . @synchronized(self) { _delegate = delegate; } 2.需要消耗系統資源 . 3.互斥鎖是利用線程同步實現的 , 意在保證同一時間只有一個線程調用 set 方法 . 4.其實還有 get 方法 , 要是同時 set 和 get 一起調用還是會有問題的 . 所以即使用了 atomic 修飾 還是不夠安全 . ------------------------------------------------------------------------------ readonly 1.讓 Xcode 只生成get方法 . 2.不想把暴露的屬性被人隨便替換時 , 可以使用 . ------------------------------------------------------------------------------ readwrite 1.讓 Xcode 生成get/set方法 . 2.不用 readonly 修飾時 , 默認就是 readwrite . ------------------------------------------------------------------------------ getter/setter 的自定義方法名 . 1.一般對於 有/無 是/否 等這樣的屬性 , getter 方法名前面加個 is 會顯得通俗易懂 .


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM