OC - 屬性關(guān)鍵字和所有權(quán)修飾符

網(wǎng)絡(luò)配圖

目錄

  • 1. 屬性關(guān)鍵字
    ?1.1 原子性
    ?1.2 讀寫權(quán)限
    ?1.3 內(nèi)存管理
    ?1.4 可空性
  • 2. 所有權(quán)修飾符
  • 3. 相關(guān)面試題
  • 參考

1. 屬性關(guān)鍵字有哪些?

分類 屬性關(guān)鍵字
原子性 atomic、nonatomic
讀寫權(quán)限 readwrite、readonly、setter、getter
內(nèi)存管理 assign、weak、unsafe_unretained、retain、strong、copy
可空性 (nullable、_Nullable 、__nullable)、
(nonnull、_Nonnull、__nonnull)、
(null_unspecified、_Null_unspecified 、__null_unspecified)、
null_resettable

1.1 原子性

屬性關(guān)鍵字 用法
atomic 原子性(默認(rèn)),編譯器會自動生成互斥鎖,對 setter 和 getter 方法進行加鎖,可以保證屬性的賦值和取值的原子性操作是線程安全的,但不包括操作和訪問。
比如說 atomic 修飾的是一個數(shù)組的話,那么我們對數(shù)組進行賦值和取值是可以保證線程安全的。但是如果我們對數(shù)組進行操作,比如說給數(shù)組添加對象或者移除對象,是不在 atomic 的負(fù)責(zé)范圍之內(nèi)的,所以給被 atomic 修飾的數(shù)組添加對象或者移除對象是沒辦法保證線程安全的。
nonatomic 非原子性,一般屬性都用 nonatomic 進行修飾,因為 atomic 非常耗時。

1.2 讀寫權(quán)限

屬性關(guān)鍵字 用法
readwrite 可讀可寫(默認(rèn)),同時生成 setter 方法和 getter 方法的聲明和實現(xiàn)。
readonly 只讀,只生成 getter 方法的聲明和實現(xiàn)。
setter 可以指定生成的 setter 方法名,如 setter = setName。
getter 可以指定生成的 getter 方法名,如 getter = getName。

1.3 內(nèi)存管理

屬性關(guān)鍵字 用法
assign 1. 既可以修飾基本數(shù)據(jù)類型,也可以修飾對象類型;
2. setter 方法的實現(xiàn)是直接賦值,一般用于基本數(shù)據(jù)類型 ;
3. 修飾基本數(shù)據(jù)類型,如 NSInteger、BOOL、int、float 等;
4. 修飾對象類型時,不增加其引用計數(shù);
5. 會產(chǎn)生懸垂指針(懸垂指針:assign 修飾的對象在被釋放之后,指針仍然指向原對象地址,該指針變?yōu)閼掖怪羔槨_@時候如果繼續(xù)通過該指針訪問原對象的話,就可能導(dǎo)致程序崩潰)。
weak 1. 只能修飾對象類型;
2. ARC 下才能使用;
3. 修飾弱引用,不增加對象引用計數(shù),主要可以用于避免循環(huán)引用;
4. weak 修飾的對象在被釋放之后,會自動將指針置為 nil,不會產(chǎn)生懸垂指針。
unsafe_unretained 1. 既可以修飾基本數(shù)據(jù)類型,也可以修飾對象類型;
2. MRC 下經(jīng)常使用,ARC 下基本不用;
3. 同 weak,區(qū)別就在于 unsafe_unretained 會產(chǎn)生懸垂指針。
retain 1. MRC 下使用,ARC 下基本使用 strong;
2. 修飾強引用,將指針原來指向的舊對象釋放掉,然后指向新對象,同時將新對象的引用計數(shù)加1;
3. setter 方法的實現(xiàn)是 release 舊值,retain 新值,用于OC對象類型。
strong 1. ARC 下才能使用;
2. 原理同 retain;
3. 但是在修飾 block 時,strong 相當(dāng)于 copy,而 retain 相當(dāng)于 assign。
copy setter 方法的實現(xiàn)是 release 舊值,copy 新值,用于 NSString、block 等類型。

1.4 可空性

iOS 混編|為 Objective-C API 指定可空性

2. 所有權(quán)修飾符

所有權(quán)修飾符 用法
__strong 1.強引用持有對象,可以對應(yīng) strong、retain、copy 關(guān)鍵字。
2.編譯器將為 strong、retain、copy 修飾的屬性生成帶 __strong 所有權(quán)修飾符的實例變量。
__weak 1.弱引用持有對象,對應(yīng) weak 關(guān)鍵字,ARC下用來防止循環(huán)引用。
2.編譯器將為 weak 修飾的屬性生成帶 __weak 所有權(quán)修飾符的實例變量。
__unsafe_unretained 1.弱引用持有對象,對應(yīng) unsafe_unretained、assign 關(guān)鍵字,MRC下用來防止循環(huán)引用。
2.編譯器將為 unsafe_unretained 修飾的屬性生成帶 __unsafe_unretained 所有權(quán)修飾符的實例變量。
3.與 __weak 相比,它不需要遍歷 weak 表來檢查對象是否 nil,性能上要更好一些。但是它會產(chǎn)生懸垂指針。
__autoreleasing 在 MRC 中我們可以給對象發(fā)送 autorelease 消息來將它注冊到 autoreleasepool 中,而在 ARC 中我們可以使用 __autoreleasing 修飾符修飾對象將對象注冊到 autoreleasepool 中。

關(guān)于所有權(quán)修飾符的詳細(xì)解釋,可以參閱《iOS - 老生常談內(nèi)存管理(三):ARC 面世》

3. 相關(guān)面試題

Q:atomic 修飾的屬性是怎么樣保存線程安全的?

答:編譯器會自動生成互斥鎖,對 setter 和 getter 方法進行加鎖,可以保證屬性的賦值和取值原子性操作是線程安全的,但不包括操作和訪問。
比如說atomic修飾的是一個數(shù)組的話,那么我們對數(shù)組進行賦值和取值是可以保證線程安全的。但是如果我們對數(shù)組進行操作,比如說給數(shù)組添加對象或者移除對象,是不在atomic的負(fù)責(zé)范圍之內(nèi)的,所以給被atomic修飾的數(shù)組添加對象或者移除對象是沒辦法保證線程安全的。

Q:什么時候使用 weak/__weak 關(guān)鍵字?

  • ① ARC 中為了避免循環(huán)引用而使用,可以讓相互引用的對象中的一個使用weak/__weak弱引用修飾,常用于對delegateblock的修飾;
  • ② Interface Builder 中 IBOutlet 修飾的控件一般也是用weak

Q:assign 和 weak 關(guān)鍵字的區(qū)別有哪些?

  • weak只能修飾對象,而assign既可以修飾對象也可以修飾基本數(shù)據(jù)類型;
  • assign修飾的對象在被釋放后,指針仍然指向原對象地址;而weak修飾的對象在被釋放之后會自動置指針為 nil;
  • ③ 相同點:在修飾對象的時候,assignweak都不改變對象的引用計數(shù)。

Q:以下代碼會出現(xiàn)什么問題?(深淺拷貝)

@property (copy) NSMutableArray *array;

答:不論賦值過來的是NSMutableArray還是NSArray對象,進行copy操作后都是NSArray對象(深拷貝)。由于屬性被聲明為NSMutableArray類型,就不可避免的會有調(diào)用方去調(diào)用它的添加對象、移除對象等一些方法,此時由于copy的結(jié)果是NSArray不可變對象,對NSArray對象調(diào)用添加對象、移除對象等方法,就會產(chǎn)生程序異常。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。