Copy修饰的NSArray
深復制與淺復制
簡單點理解,深復制,在內存中拷貝一份新的對象。 淺復制,沒有拷貝新的對象,只是一個地址的引用。 在賦值過程中深復制操作,原對象的引用計數不會增加,淺復制引用計數會加一。
copy操作和mutableCopy操作
一個類遵循NSCopying,NSMutableCopying協議并且實現相對應的初始化方法后,這個類就具有對象拷貝的能力。如果你自定義類沒有遵守協議直接調用copy/mutableCopy程序會奔潰。拷貝協議的具體使用我這里不做擴展感興趣的可以自行Google一下。有一些剛接觸iOS開發的同學認為copy操作就是淺復制,mutableCopy就是深復制,這是一個非常錯誤的理解。以下是我的一些總結:
- 可變的集合對象 + copy 得到一個新的對象(新對象不可變)深復制
- 可變的集合對象 + mutablecopy 得到一個新的對象(新對象可變)深復制
- 不可變集合對象 + copy 沒有得到新的對象(地址的引用)淺復制
- 不可變集合對象 + mutablecopy 得到一個新的對象(新對象可變)深復制 OC中集合對象NSArray、NSMutableArray、NSDictionary、NSMutableDictionary、NSSet、NSMutableSet等,另外NSString、NSMutableString也準守以上原則。實踐出真理我們來看看代碼中的效果:
我們選取NSArray、NSMutableArray來看一下copy和mutableCopy的結果
stong與copy修飾符
strong和copy都可以用來修飾對象類型屬性,strong修飾的屬性,在將一個對象賦值給這個屬性的時候,對象不會進行內存的拷貝,直接進行地址的引用,對象的引用計數+1;copy修飾的屬性,如果該屬性是一個非集合類型,那么賦值操作的效果和strong是一樣的,如果該屬性是一個集合類型,我們在下面在詳細的解讀。
NSMutableArray屬性請使用strong修飾符
數學里面一個證明方式叫做反證法,接下來我們自定義一個類,增加一個NSMutableArray屬性,使用copy來修飾
#import <Foundation/Foundation.h> @interface TestObject : NSObject @property (nonatomic, copy) NSMutableArray *mutableArr; @end#import "TestObject.h" @implementation TestObject - (instancetype)init{self = [super init]; // self.mutableArr = [NSMutableArray arrayWithObject:@"1"];_mutableArr = [NSMutableArray arrayWithObject:@"1"];[self.mutableArr addObject:@"2"];//這一步,如果使用點語法進行屬性賦值,程序crash;如果直接使用成員變量方式賦值,代碼沒有問題return self; }//一般情況編譯器會自動給屬性添加get/set方法 - (void)setMutableArr:(NSMutableArray *)mutableArr{_mutableArr = [mutableArr copy]; } @end 復制代碼執行下面代碼
TestObject *testObject = [TestObject new]; testObject.mutableArr = [NSMutableArray arrayWithObject:@"1"]; [testObject.mutableArr addObject:@"2"]; 復制代碼程序crash,控制臺提示錯誤 [__NSSingleObjectArrayI addObject:]: unrecognized selector sent to instance 0x1c0017730 這一步我們就證明了如果我們使用copy來修飾一個可變的數組屬性,然后通過點語法的方式把一個可變的數組賦值給該屬性,最后該屬性指向的是一個拷貝得到的全新的不可變數組,這個時候我們可以在代碼中調用arrayWithObject等改變數組的api(因為@property (nonatomic, copy) NSMutableArray *mutableArr 告訴編譯器這是一個可變的數組),但是在運行時,這個屬性指向的是一個不可變的數組,引發unrecognized selector sent to instance 錯誤,從而導致crash。
NSArray屬性請使用copy修飾符
我們定義一個NSArray類型的屬性,目的是為了在初始化或者賦值操作后,這個數組集合就不能夠改變的(增加或者刪除元素等)。如果我們使用strong去修飾NSArray屬性,并且我們把一個可變的數組NSMutableArray對象賦值給了該屬性(父類的指針可以指向子類對象),strong并不會在內存中拷貝新的對象,只是一個地址的引用,所以NSArray類型的屬性實質上指向的是一個NSMutableArray,這個時候如果其他地方還有一個NSMutableArray指針變量指向這個NSMutableArray對象,并且通過這個變量改變了數組,也會造成NSArray類型屬性的改變,因為它們指向是一個地址內存,也就是一個對象。這就違背了我們設計的初衷,同時可能引發一些業務邏輯問題。
尾語
以上內容有任何的疑問、錯誤,請各路大神指出,同時希望能夠幫助到大家
總結
以上是生活随笔為你收集整理的Copy修饰的NSArray的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux下CURL设置请求超时时间
- 下一篇: Cocos2dx源码记录(11) C