iOS copy & mutableCopy

  • 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:深復制,副本可變

總之,不管源對象是否可變,副本都是可變的。

  • 注意: 普通對象&集合類對象的區(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.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容