記開發(fā)中一個問題,關(guān)于copy和mutableCopy

首先我們先看一段代碼,

這是一個模型,里面有四個屬性
@interface YCTeacherShowUserInfoModel : NSObject

/** 用戶ID */
@property (nonatomic, copy) NSString *_id;
/** 昵稱 */
@property (nonatomic, copy) NSString *nickname;
/** 等級 */
@property (nonatomic, assign) NSInteger level;
/** 頭像 */
@property (nonatomic, copy) NSString *avatar;

@end

然后進行下面的操作:

    YCTeacherShowUserInfoModel *model1 = [[YCTeacherShowUserInfoModel alloc] init];
    model1.nickname = @"哈哈1";
    model1.avatar = @"圖片1";
    
    YCTeacherShowUserInfoModel *model2 = [[YCTeacherShowUserInfoModel alloc] init];
    model2.nickname = @"哈哈2";
    model2.avatar = @"圖片2";
    
    NSArray *normaleArr = @[model1, model2];
    NSArray *tempArr = normaleArr;
    NSMutableArray *listArray = [NSMutableArray arrayWithArray:tempArr];
    
    [listArray enumerateObjectsUsingBlock:^(YCTeacherShowUserInfoModel *obj, NSUInteger idx, BOOL * _Nonnull stop) {
        obj.nickname = @"呵呵呵";
    }];
    
    NSLog(@"------%@", normaleArr);

我們來分析一下,這個代碼,剛開始的時候,我覺得這個結(jié)果,normalArr數(shù)組沒有發(fā)生變化,但是打印的結(jié)果卻讓我大吃一驚,normalArr中的模型的nickname屬性都變成了呵呵呵, 然后通過控制臺可以看出

WechatIMG14.jpeg

分析一下原因,如下圖:

WechatIMG15.jpeg

從上面這張圖可以看出,為什么我們修改model的屬性的值的時候,會改變normal數(shù)組中模型的值了。

對于上面這個問題,我們應(yīng)該怎么解決呢,首先我們分析一下,如何首先分析一下,

  • 對于系統(tǒng)的容器類對象,對不可變對象(如 NSArray)進行復(fù)制,copy 是指針復(fù)制(淺拷貝), mutableCopy 是對象復(fù)制(深拷貝), 但是不管是 copy 還是 mutableCopy, 且不論容器內(nèi)對象是可變還是不可變,返回的容器內(nèi)對象都是指針復(fù)制(淺拷貝)。
  • 對于系統(tǒng)的容器類對象,對可變對象(如 NSMutableArray)進行復(fù)制時,copy 和 mutableCopy 都是對象復(fù)制(深拷貝),但是不管是 copy 還是 mutableCopy,且不論容器內(nèi)對象是可變還是不可變,返回的容器內(nèi)對象都是指針復(fù)制(淺拷貝)。

基于上面的結(jié)論,淺復(fù)制,并不拷貝對象本身,僅僅是拷貝指向?qū)ο蟮闹羔槪簧顝?fù)制是直接拷貝整個對象內(nèi)存到另一塊內(nèi)存中。所以我們應(yīng)該讓對象具備深copy能力,也就是具備copy內(nèi)容的能力。讓對象具備copy能力的前提是讓對象遵守 NSCopying協(xié)議,如果讓對象同時具備mutableCopy能力,同樣要遵守NSMutableCopying協(xié)議,所以對于YCTeacherShowUserInfoModel來說,應(yīng)該:

#import "YCTeacherShowUserInfoModel.h"

@interface YCTeacherShowUserInfoModel()<NSCopying, NSMutableCopying>

@end

@implementation YCTeacherShowUserInfoModel

- (id)copyWithZone:(NSZone *)zone {
    YCTeacherShowUserInfoModel *user = [[YCTeacherShowUserInfoModel allocWithZone:zone] init];
    user._id = self._id;
    user.nickname = self.nickname;
    user.avatar = self.avatar;
    user.level = self.level;
    return user;
}

- (id)mutableCopyWithZone:(NSZone *)zone {
    
    YCTeacherShowUserInfoModel *user = [[YCTeacherShowUserInfoModel allocWithZone:zone] init];
    user._id = self._id;
    user.nickname = self.nickname;
    user.avatar = self.avatar;
    user.level = self.level;
    return user;
}

@end

然后在調(diào)用的時候,只需要按照下面的姿勢就可以了,就可以實現(xiàn)修改listArray中對象的值的時候,不會影響normalArray中對象的值。

    YCTeacherShowUserInfoModel *model1 = [[YCTeacherShowUserInfoModel alloc] init];
    model1.nickname = @"哈哈1";
    model1.avatar = @"圖片1";
    
    YCTeacherShowUserInfoModel *model2 = [[YCTeacherShowUserInfoModel alloc] init];
    model2.nickname = @"哈哈2";
    model2.avatar = @"圖片2";
    
    NSArray *normaleArr = @[model1, model2];
    
    NSMutableArray *listArray = [NSMutableArray array];
    for (YCTeacherShowUserInfoModel *model in normaleArr) {
        [listArray addObject:model.copy];
    }
    
    [listArray enumerateObjectsUsingBlock:^(YCTeacherShowUserInfoModel *obj, NSUInteger idx, BOOL * _Nonnull stop) {
        obj.nickname = @"呵呵呵";
    }];

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 前言 不敢說覆蓋OC中所有copy的知識點,但最起碼是目前最全的最新的一篇關(guān)于 copy的技術(shù)文檔了。后續(xù)發(fā)現(xiàn)有新...
    zyydeveloper閱讀 3,422評論 4 35
  • 本文為轉(zhuǎn)載: 作者:zyydeveloper 鏈接:http://www.lxweimin.com/p/5f776a...
    Buddha_like閱讀 914評論 0 2
  • 一、從面向?qū)ο蟮絆bjective-C概覽copy 面向?qū)ο螅?在面向?qū)ο蟮某绦蛟O(shè)計中,對象的copy就是創(chuàng)建一個...
    被吹落的風(fēng)閱讀 523評論 0 2
  • 其實我一直對于例如屬性中的copy OR [array copy]這樣的使用稀里糊涂的。之前有總結(jié)過,無奈現(xiàn)在又忘...
    升級打怪啊怪閱讀 1,268評論 0 3
  • 一、從面向?qū)ο蟮絆bjective-C概覽copy 1、面向?qū)ο螅?In object-oriented prog...
    adrian920閱讀 775評論 0 3