- Copy的目的是建立副本,同時修改原始對象和復本不會互相干擾.
淺拷貝 & 淺拷貝
淺拷貝
淺拷貝是指針拷貝,對一個對象進行淺拷貝,相當于對指向這個對象的指針進行復制,產生了
一個新的指向這個對象的指針,那么就是有兩個指針指向同一個對象,這個對象銷毀后兩個指
針都應該置為空。
對象的引用計數+1, 其實相當于做了一次retain操作.
retain屬性特性是指針拷貝,創(chuàng)建一個指針,引用對象計數加1.
深拷貝
深拷貝是內容拷貝,相當于對對象進行復制,產生一個新的對象,那么就有兩個指針分別指向
兩個對象。對一個對象的操作不會影響到另一個。
copy屬性特性新的對象的引用計數為1,和舊有對象的引用計數無關,舊有對象沒有變化。
只有不可變對象創(chuàng)建不可變副本(copy)才是淺復制, 其他都是深復制.
copy和mutableCopy存在的原因: 盡可能的節(jié)省內存開銷.
copy和mutableCopy方法
在iOS中不是所有對象支持copy、mutableCopy,遵守NSCopying協議的類可以發(fā)送copy消息,
遵守NSMutableCopy協議的類才可以發(fā)送mutableCopy消息。
假如發(fā)送了一個沒有遵守上訴兩協議而發(fā)送 copy或者 mutableCopy,那么就會發(fā)生異常。
但是默認的ios類并沒有遵守這兩個協議。
- 自定義copy mutableCopy的條件:
如果想自定義一下copy 那么就必須遵守NSCopying,并且實現 copyWithZone: 方法,
如果想自定義一下mutableCopy 那么就必須遵守NSMutableCopying,并且實現
mutableCopyWithZone: 方法。
區(qū)別:copy、mutableCopy、retain的區(qū)別(可用集合類和非集合類的可變和不可變對象證明)
copy返回一個不可變對象的副本,不能修改;mutableCopy返回一個可變對象的副本,可以修改。
對于不可變對象:
copy:淺復制,相當于retain。
mutableCopy:深復制,副本可變-
對于可變對象:
- copy:深復制,但是副本不可變, 即復制對象為一份不可變的對象. 所以,
這里不能對副本做增刪修改.比如NSMutableArray.copy做刪除操作會crash. - mutableCopy:深復制,副本可變
- copy:深復制,但是副本不可變, 即復制對象為一份不可變的對象. 所以,
總之,不管源對象是否可變,副本都是可變的。
注意: 普通對象&集合類對象的區(qū)分, 集合類對象的元素指針總是拷貝之前的指針, 也就是元素只進行了淺拷貝.
舉例:
- (void)testCopy
{
///不可變對象
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
*/
///集合類對象.
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(@"集合類對象\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>"
)
可以看出集合內的元素只是進行了淺拷貝
*/
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(@"可變集合類對象");
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>"
)
*/
}
對象的自定義拷貝
例如:@property(nonatomic,retain)NSString *name;
對象擁有復制特性,必須遵守NSCopying,NSMutableCopying協議,實現該協議的
copyWithZone方法和mutableCopyWithZone方法。
深拷貝和淺拷貝的區(qū)別就在于copyWithZone方法的實現,方法內部一個創(chuàng)建了新的內存空間,一個沒有。
多態(tài)的影響
例如:
NSString *str = [[NSMutableString alloc] initWithString:@"aaa"];
[str copy];
這個copy調用的是NSMutableString的copyWithZone. OC對多態(tài)的支持本質上是消息機制中的isa始終沒變, isa指向NSMutableString.