網(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
弱引用修飾,常用于對delegate
和block
的修飾; - ② Interface Builder 中 IBOutlet 修飾的控件一般也是用
weak
。
Q:assign 和 weak 關(guān)鍵字的區(qū)別有哪些?
- ①
weak
只能修飾對象,而assign
既可以修飾對象也可以修飾基本數(shù)據(jù)類型; - ②
assign
修飾的對象在被釋放后,指針仍然指向原對象地址;而weak
修飾的對象在被釋放之后會自動置指針為 nil; - ③ 相同點:在修飾對象的時候,
assign
和weak
都不改變對象的引用計數(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)生程序異常。