大家好半夷,我是西瓜,現(xiàn)居廣州极颓。在今年想要回顧梳理一下OC的相關(guān)知識點盅藻。今天就先從基礎(chǔ)但不簡單的深拷貝與淺拷貝開始吧购桑。
我們從一道當初很出名的面試題開始我們今天的學習:
為什么NSString要用copy修飾而不是strong?
我們先看第一個問題氏淑,為什么NSString要用copy而不用strong勃蜘。但凡有iOS基礎(chǔ)的同學們都知道,NSString是一個對象夸政,而對象就是用strong元旬,保證強引用不被釋放榴徐。與strong屬于同一層級的修飾詞還有weak守问,assign,copy坑资。weak和assign可以輕松的理解耗帕,唯獨讓人困惑的就是copy的用法。
接下里我們先看一段代碼:
@interface Person : NSObject
@property (nonatomic, copy) NSArray *array_copy;
@property (nonatomic, strong) NSArray *array_strong;
@end
Person *p1 = [[Person alloc] init];
NSMutableArray *array = [NSMutableArray arrayWithObjects:@"1", nil];
p1.array_copy = array;
p1.array_strong = array;
NSLog(@"addObject之前 array 地址%p 值%@", array, array);
NSLog(@"addObject之前 array_strong 地址%p 值%@", p1.array_strong, p1.array_strong);
NSLog(@"addObject之前 array_copy 地址%p 值%@", p1.array_copy, p1.array_copy);
[array addObject:@"2"];
NSLog(@"addObject之后 array 地址%p 值%@", array, array);
NSLog(@"addObject之后 array_strong 地址%p 值%@", p1.array_strong, p1.array_strong);
NSLog(@"addObject之后 array_copy 地址%p 值%@", p1.array_copy, p1.array_copy);
打印結(jié)果如下:
2017-02-27 20:48:31.750 test[49360:1849602] addObject之前 array 地址0x60800005cc20 值(
1
)
2017-02-27 20:48:31.750 test[49360:1849602] addObject之前 array_strong 地址0x60800005cc20 值(
1
)
2017-02-27 20:48:31.751 test[49360:1849602] addObject之前 array_copy 地址0x608000011d30 值(
1
)
2017-02-27 20:48:31.751 test[49360:1849602] addObject之后 array 地址0x60800005cc20 值(
1,
2
)
2017-02-27 20:48:31.751 test[49360:1849602] addObject之后 array_strong 地址0x60800005cc20 值(
1,
2
)
2017-02-27 20:48:31.751 test[49360:1849602] addObject之后 array_copy 地址0x608000011d30 值(
1
)
有基礎(chǔ)的同學看看這段代碼袱贮,然后仔細思考一番應(yīng)該就能想通為什么是這個打印結(jié)果了仿便。
不過沒事,下面我會來一一講解攒巍。
我們首先創(chuàng)建了一個可變數(shù)組叫array
嗽仪,接著把array
賦值給Person
的兩個屬性,這兩個屬性都是不可變數(shù)組柒莉,唯一的區(qū)別就是一個用copy
修飾闻坚,一個用strong
修飾。
接著我們分別打印array
兢孝,array_strong
窿凤,array_copy
的值和地址,發(fā)現(xiàn)三個數(shù)組的值都是一樣的跨蟹,但array_copy
的地址卻和其他兩個數(shù)組不相同雳殊,這是為什么呢?
最后我們給array
可變數(shù)組添加一個字符串窗轩,再次打印夯秃,發(fā)現(xiàn)array
和array_copy
無論是地址還是值都一樣,但array_strong
卻獨樹一幟,無論是值還是地址仓洼,都和其它二位不相同箫措。
其中p1.array_copy = array
由于array_copy
是copy
修飾的,所以這段代碼會產(chǎn)生類似于p1.array_copy = [array copy]
的效果衬潦。
出現(xiàn)這樣的原因就是因為發(fā)生了深拷貝和淺拷貝斤蔓。
通俗來說,指針有變化就是深拷貝镀岛,指針無變化就是淺拷貝
如果把Person
中的數(shù)組變成NSString
弦牡,結(jié)果也是類似的。這樣我們就可以回答第一個問題了:
NSString
使用copy
是為了防止被賦值后再被外界所修改按道理講
NSArray
漂羊,NSDictionary
這些容器對象也應(yīng)該使用copy
驾锰,以防止出現(xiàn)上述例子中出現(xiàn)的問題,但這個說法早就已經(jīng)過時了走越。使用copy
還是strong
完全取決于你的需求椭豫。你希望跟隨外界改動就用strong
,不希望就用copy
旨指。
粗略的畫了這張圖來解釋上述例子赏酥,不要介意:
所以我們可以得出簡單的結(jié)論
淺拷貝:一個指針,指向一塊內(nèi)存谆构, 對這塊內(nèi)存進行淺拷貝裸扶,其實就是提取了這塊內(nèi)存的地址,把他給另外一個指針類型存放搬素。
綜合來看呵晨,內(nèi)存并未有任何變化,但是現(xiàn)在有兩個指針指向它熬尺。并且這兩個指針存放的值一樣摸屠,就是這塊內(nèi)存的地址,但是這兩個指針本身的內(nèi)存地址不一樣粱哼,所以就是兩個不同的指針指向同一塊內(nèi)存季二。
深拷貝: 一個指針,指向一塊內(nèi)存1皂吮,對這塊內(nèi)存1進行深拷貝戒傻,首先,我要開辟一塊跟這塊內(nèi)存一樣大的內(nèi)存2蜂筹,然后把內(nèi)存1里面的值(請注意需纳,這里是值)的復制到內(nèi)存2里,然后再建一個指針艺挪,指向內(nèi)存2不翩。
這時候來看兵扬,存在兩塊內(nèi)存,并且兩塊內(nèi)存毫不相干口蝠,只是里面的值暫時一樣而已器钟。 修改其中一個也不會影響另一個。
第一次寫技術(shù)文章妙蔗,肯定有諸多不足傲霸,請多包容。如果有不懂的或者想要技術(shù)交流都可以私信我眉反,謝謝大家昙啄。