- Copy的目的是建立副本炉峰,同時(shí)修改原始對(duì)象和復(fù)本不會(huì)互相干擾.
淺拷貝 & 淺拷貝
淺拷貝
淺拷貝是指針拷貝,對(duì)一個(gè)對(duì)象進(jìn)行淺拷貝叮姑,相當(dāng)于對(duì)指向這個(gè)對(duì)象的指針進(jìn)行復(fù)制广料,產(chǎn)生了
一個(gè)新的指向這個(gè)對(duì)象的指針砾脑,那么就是有兩個(gè)指針指向同一個(gè)對(duì)象,這個(gè)對(duì)象銷(xiāo)毀后兩個(gè)指
針都應(yīng)該置為空艾杏。
對(duì)象的引用計(jì)數(shù)+1, 其實(shí)相當(dāng)于做了一次retain操作.
retain屬性特性是指針拷貝韧衣,創(chuàng)建一個(gè)指針,引用對(duì)象計(jì)數(shù)加1.
深拷貝
深拷貝是內(nèi)容拷貝购桑,相當(dāng)于對(duì)對(duì)象進(jìn)行復(fù)制畅铭,產(chǎn)生一個(gè)新的對(duì)象,那么就有兩個(gè)指針?lè)謩e指向
兩個(gè)對(duì)象勃蜘。對(duì)一個(gè)對(duì)象的操作不會(huì)影響到另一個(gè)硕噩。
copy屬性特性新的對(duì)象的引用計(jì)數(shù)為1,和舊有對(duì)象的引用計(jì)數(shù)無(wú)關(guān)缭贡,舊有對(duì)象沒(méi)有變化炉擅。
只有不可變對(duì)象創(chuàng)建不可變副本(copy)才是淺復(fù)制, 其他都是深復(fù)制
.
copy和mutableCopy存在的原因: 盡可能的節(jié)省內(nèi)存開(kāi)銷(xiāo).
copy和mutableCopy方法
在iOS中不是所有對(duì)象支持copy、mutableCopy匀归,遵守NSCopying協(xié)議的類(lèi)可以發(fā)送copy消息坑资,
遵守NSMutableCopy協(xié)議的類(lèi)才可以發(fā)送mutableCopy消息。
假如發(fā)送了一個(gè)沒(méi)有遵守上訴兩協(xié)議而發(fā)送 copy或者 mutableCopy,那么就會(huì)發(fā)生異常穆端。
但是默認(rèn)的ios類(lèi)并沒(méi)有遵守這兩個(gè)協(xié)議。
- 自定義copy mutableCopy的條件:
如果想自定義一下copy 那么就必須遵守NSCopying,并且實(shí)現(xiàn) copyWithZone: 方法仿便,
如果想自定義一下mutableCopy 那么就必須遵守NSMutableCopying,并且實(shí)現(xiàn)
mutableCopyWithZone: 方法体啰。
區(qū)別:copy攒巍、mutableCopy、retain的區(qū)別(可用集合類(lèi)和非集合類(lèi)的可變和不可變對(duì)象證明)
copy返回一個(gè)不可變對(duì)象的副本荒勇,不能修改柒莉;mutableCopy返回一個(gè)可變對(duì)象的副本,可以修改沽翔。
對(duì)于不可變對(duì)象:
copy:淺復(fù)制兢孝,相當(dāng)于retain。
mutableCopy:深復(fù)制仅偎,副本可變-
對(duì)于可變對(duì)象:
- copy:深復(fù)制跨蟹,但是副本不可變, 即復(fù)制對(duì)象為一份不可變的對(duì)象. 所以,
這里不能對(duì)副本做增刪修改.比如NSMutableArray.copy做刪除操作會(huì)crash
. - mutableCopy:深復(fù)制,副本可變
- copy:深復(fù)制跨蟹,但是副本不可變, 即復(fù)制對(duì)象為一份不可變的對(duì)象. 所以,
總之橘沥,不管源對(duì)象是否可變窗轩,副本都是可變的。
注意: 普通對(duì)象&集合類(lèi)對(duì)象的區(qū)分, 集合類(lèi)對(duì)象的元素指針總是拷貝之前的指針, 也就是元素只進(jìn)行了淺拷貝.
舉例:
- (void)testCopy
{
///不可變對(duì)象
NSString *i_originValue = @"abcd";
NSString *i_copyValue = [i_originValue copy];
NSString *i_mutableCopyValue = [i_originValue mutableCopy];
NSLog(@"i_originValue_%p \n i_copyValue_%p \n i_mutableCopyValue_%p",i_originValue,i_copyValue,i_mutableCopyValue);
/**
i_originValue_0x1025743f0
i_copyValue_0x1025743f0
i_mutableCopyValue_0x600003948420
*/
NSMutableString *m_originValue = [NSMutableString stringWithString:@"abcd"];
NSString *m_copyValue = [m_originValue copy];
NSString *m_mutableCopyValue = [m_originValue mutableCopy];
NSLog(@"m_originValue_%p \n m_copyValue_%p \n m_mutableCopyValue_%p",m_originValue,m_copyValue,m_mutableCopyValue);
/**
m_originValue_0x600003948540
m_copyValue_0xc441772269513b02
m_mutableCopyValue_0x600003948f30
*/
///集合類(lèi)對(duì)象.
WeakTestObj *item1 = [[WeakTestObj alloc] init];
item1.title = @"abcd";
WeakTestObj *item2 = [[WeakTestObj alloc] init];
item2.title = @"abcd";
NSArray *i_collection_originValue = @[item1,item2];
NSArray *i_collection_copyValue = [i_collection_originValue copy];
NSArray *i_collection_mutableCopyValue = [i_collection_originValue mutableCopy];
NSLog(@"集合類(lèi)對(duì)象\n");
NSLog(@"i_collection_originValue_%p_%@",i_collection_originValue,i_collection_originValue);
NSLog(@"i_collection_copyValue_%p_%@",i_collection_copyValue,i_collection_copyValue);
NSLog(@"i_collection_mutableCopyValue_%p_%@",i_collection_mutableCopyValue,i_collection_mutableCopyValue);
/**
i_collection_originValue_0x60000375c2e0_(
"<WeakTestObj: 0x60000375c240>",
"<WeakTestObj: 0x60000375c840>"
)
i_collection_copyValue_0x60000375c2e0_(
"<WeakTestObj: 0x60000375c240>",
"<WeakTestObj: 0x60000375c840>"
)
i_collection_mutableCopyValue_0x600003950180_(
"<WeakTestObj: 0x60000375c240>",
"<WeakTestObj: 0x60000375c840>"
)
可以看出集合內(nèi)的元素只是進(jìn)行了淺拷貝
*/
NSMutableArray *m_collection_originValue = [NSMutableArray arrayWithObjects:item1,item2, nil];
NSMutableArray *m_collection_copyValue = [m_collection_originValue copy];
NSMutableArray *m_collection_mutableCopyValue = [m_collection_originValue mutableCopy];
NSLog(@"可變集合類(lèi)對(duì)象");
NSLog(@"m_collection_originValue_%p_%@",m_collection_originValue,m_collection_originValue);
NSLog(@"m_collection_copyValue_%p_%@",m_collection_copyValue,m_collection_copyValue);
NSLog(@"m_collection_mutableCopyValue_%p_%@",m_collection_mutableCopyValue,i_collection_mutableCopyValue);
/**
m_collection_originValue_0x60000394c480_(
"<WeakTestObj: 0x60000375c240>",
"<WeakTestObj: 0x60000375c840>"
)
m_collection_copyValue_0x600003754c80_(
"<WeakTestObj: 0x60000375c240>",
"<WeakTestObj: 0x60000375c840>"
)
m_collection_mutableCopyValue_0x60000394c3c0_(
"<WeakTestObj: 0x60000375c240>",
"<WeakTestObj: 0x60000375c840>"
)
*/
}
對(duì)象的自定義拷貝
例如:@property(nonatomic,retain)NSString *name;
對(duì)象擁有復(fù)制特性座咆,必須遵守NSCopying痢艺,NSMutableCopying協(xié)議,實(shí)現(xiàn)該協(xié)議的
copyWithZone方法和mutableCopyWithZone方法介陶。
深拷貝和淺拷貝的區(qū)別就在于copyWithZone方法的實(shí)現(xiàn)堤舒,方法內(nèi)部一個(gè)創(chuàng)建了新的內(nèi)存空間,一個(gè)沒(méi)有哺呜。
多態(tài)的影響
例如:
NSString *str = [[NSMutableString alloc] initWithString:@"aaa"];
[str copy];
這個(gè)copy調(diào)用的是NSMutableString的copyWithZone. OC對(duì)多態(tài)的支持本質(zhì)上是消息機(jī)制中的isa始終沒(méi)變, isa指向NSMutableString.