前言
在iOS中并不是所有對象都支持copy和mutableCopy的.必須要遵守<NSCopying,NSMutableCopying>兩個協(xié)議.只有遵守了這兩個協(xié)議的類才有權限發(fā)送copy和mutableCopy消息,我自己試驗了一把,如果我沒有遵守協(xié)議,copyWithZone以及mutableCopyWithZone是沒有提示的,如果我們強制運行這兩個方法,程序會直接崩潰.當讓如果我們直接調(diào)用copy和mutableCopy對象方法,運行也會崩潰,提示我們需要遵守這兩個協(xié)議
-
淺拷貝
- 所謂的淺拷貝就是拷貝指向?qū)ο蟮闹羔?意思就是說:拷貝出來的目標對象的指針和源對象的指針指向的內(nèi)存空間是同一塊空間.
- 淺拷貝只是一種簡單的拷貝,讓幾個對象公用一個內(nèi)存,然而當內(nèi)存銷毀的時候,指向這個內(nèi)存空間的所有指針需要重新定義,不然會造成野指針錯誤
-
深拷貝
- 所謂的深拷貝指拷貝對象的具體內(nèi)容,其內(nèi)容地址是自助分配的,拷貝結(jié)束之后,內(nèi)存中的值是完全相同的,但是內(nèi)存地址是不一樣的,兩個對象之間相互不影響,也互不干涉.
我們來總結(jié)一下兩者之間的原理 : 如果現(xiàn)在有一個A對象,拷貝之后得到一份新的對象A_Copy,如果時淺拷貝,那么A對象和A_Copy對象指向的就是同一個內(nèi)存的資源,它拷貝的只是一個指針而已,對象的內(nèi)容并沒有拷貝.也就是說對象的資源還是只有一份.如果這個時候我們對A_copy對象進行修改操作,那么A對象的內(nèi)容同樣會被修改.然而如果是深拷貝,拷貝的不僅僅是指針,還有內(nèi)容,拷貝的對象B_Copy會自助分配內(nèi)存,兩個對象的指針指向的是不同的內(nèi)存空間,因為A對象和B_Copy對象的內(nèi)存地址是不一樣的,所以,如果我們對B_Copy進行修改操作的話是不會影響到A對象,它們之間是互不干涉的
淺拷貝就想是您和您的影子之間的關系 : 你掛了, 你的影子也跟著掛了
深拷貝就像是您的克隆人, 你掛啦, 可你的克隆人還活著
淺拷貝和深拷貝的應用
-
oc中哪些操作實現(xiàn)淺拷貝:
第一條:retain操作例证,始終是淺復制。返回對象是否可變與被復制的對象保持一致台妆。
在 iOS 里面笔刹, 使用retain 關鍵字進行引用計數(shù)谎脯,就是一種更加保險的淺拷貝收班。他既讓幾個指針共用同一片內(nèi)存空間涮帘,又可以在release 由于計數(shù)的存在帝簇,不會輕易的銷毀內(nèi)存,達到更加簡單使用的目的来庭。
第二條:copy操作妒蔚,對于不可變對象是淺復制。引用計數(shù)每次加一。始終返回一個不可變對象面睛。
oc中哪些操作實現(xiàn)深拷貝:
第一條:copy操作絮蒿,對于可變對象為深復制尊搬,引用計數(shù)不改變叁鉴。
第二條:mutableCopy操作:始終是深復制,引用計數(shù)不改變佛寿。始終返回一個可變對象幌墓。
代碼示例
NSString *text = @"WilliamAlex";
NSString *text1 = [text copy];
NSString *text2 = [text mutableCopy];
NSMutableString *text3 = [text copy];
NSMutableString *text4 = [text mutableCopy];
NSLog(@"text=%p,text1=%p",text,text1);
NSLog(@"text=%p,text1=%p",text,text2);
NSLog(@"text=%p,text1=%p",text,text3);
NSLog(@"text=%p,text1=%p",text,text4);
打印結(jié)果
淺拷貝和深拷貝[716:38840] text=0x10697f068,text1=0x10697f068
淺拷貝和深拷貝[716:38840] text=0x10697f068,text2=0x7fce33c74be0
淺拷貝和深拷貝[716:38840] text=0x10697f068,text3=0x10697f068
淺拷貝和深拷貝[716:38840] text=0x10697f068,text4=0x7fce33c783d0
注意 :
注意需要遵循<NSCopying, NSMutableCopying>兩個協(xié)議,否則程序會崩潰
-
從打印結(jié)果中可以看出,text1,text3的地址和text是一樣的,text2和text3和text是不一樣的.可以得出結(jié)論
- 1, 說明了使用mutableCopy拷貝出了新的對象 :它們的地址不一樣,說明了它們生成了新對象
- 2, 使用了copy,它們的地址是一樣的,說明拷貝的只是指針,不會拷貝對象自身.說明它們不會產(chǎn)生新對像.
總結(jié) : 在字符串是直接賦值的時候,判斷是否生成新對象是和等號"="右邊有直接有關,如果右邊是mutableCopy那么就會生成新的對象,如果是copy就不會產(chǎn)生新的對象. 這時候的copy就是淺拷貝,而mutableCopy就是深拷貝
stringWithFormat:方法的字符串
NSString *text = [NSString stringWithFormat:@"WilliamAlex"];
NSString *text1 = [text copy];
NSString *text2 = [text mutableCopy];
NSMutableString *text3 = [text copy];
NSMutableString *text4 = [text mutableCopy];
NSLog(@"text=%p,text1=%p",text,text1);
NSLog(@"text=%p,text1=%p",text,text2);
NSLog(@"text=%p,text1=%p",text,text3);
NSLog(@"text=%p,text1=%p",text,text4);
打印結(jié)果
淺拷貝和深拷貝[734:43455] text=0x7fbaca70c890,text1=0x7fbaca70c890
淺拷貝和深拷貝[734:43455] text=0x7fbaca70c890,text1=0x7fbaca70d760
淺拷貝和深拷貝[734:43455] text=0x7fbaca70c890,text1=0x7fbaca70c890
淺拷貝和深拷貝[734:43455] text=0x7fbaca70c890,text1=0x7fbaca70d7a0
- 結(jié)果和直接賦值完全一樣
stringWithString:方法的字符串
NSString *text = [NSMutableString stringWithString:@"WilliamAlex"];
NSString *text1 = [text copy];
NSString *text2 = [text mutableCopy];
NSMutableString *text3 = [text copy];
NSMutableString *text4 = [text mutableCopy];
NSLog(@"text=%p,text1=%p",text,text1);
NSLog(@"text=%p,text1=%p",text,text2);
NSLog(@"text=%p,text1=%p",text,text3);
NSLog(@"text=%p,text1=%p",text,text4);
打印結(jié)果
淺拷貝和深拷貝[762:45587] text=0x7fbd495aaf20,text1=0x7fbd495aac50
淺拷貝和深拷貝[762:45587] text=0x7fbd495aaf20,text1=0x7fbd495afad0
淺拷貝和深拷貝[762:45587] text=0x7fbd495aaf20,text1=0x7fbd495af810
淺拷貝和深拷貝[762:45587] text=0x7fbd495aaf20,text1=0x7fbd495acdf0
結(jié)果全部都不一樣
總結(jié) : 根據(jù)代碼,等號"="右邊從創(chuàng)建一直到賦值,它包含了一個NSMutableCopying,所以它會重新生成一個對象,copy是指針拷貝,而mutableCopy是對象拷貝.