美文网首页
记开发中一个问题,关于copy和mutableCopy

记开发中一个问题,关于copy和mutableCopy

作者: 思考的快与慢 | 来源:发表于2017-06-16 14:05 被阅读57次

    首先我们先看一段代码,

    这是一个模型,里面有四个属性
    @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);
    

    我们来分析一下,这个代码,刚开始的时候,我觉得这个结果,normalArr数组没有发生变化,但是打印的结果却让我大吃一惊,normalArr中的模型的nickname属性都变成了呵呵呵, 然后通过控制台可以看出

    WechatIMG14.jpeg

    分析一下原因,如下图:

    WechatIMG15.jpeg

    从上面这张图可以看出,为什么我们修改model的属性的值的时候,会改变normal数组中模型的值了。

    对于上面这个问题,我们应该怎么解决呢,首先我们分析一下,如何首先分析一下,

    • 对于系统的容器类对象,对不可变对象(如 NSArray)进行复制,copy 是指针复制(浅拷贝), mutableCopy 是对象复制(深拷贝), 但是不管是 copy 还是 mutableCopy, 且不论容器内对象是可变还是不可变,返回的容器内对象都是指针复制(浅拷贝)。
    • 对于系统的容器类对象,对可变对象(如 NSMutableArray)进行复制时,copy 和 mutableCopy 都是对象复制(深拷贝),但是不管是 copy 还是 mutableCopy,且不论容器内对象是可变还是不可变,返回的容器内对象都是指针复制(浅拷贝)。

    基于上面的结论,浅复制,并不拷贝对象本身,仅仅是拷贝指向对象的指针;深复制是直接拷贝整个对象内存到另一块内存中。所以我们应该让对象具备深copy能力,也就是具备copy内容的能力。让对象具备copy能力的前提是让对象遵守 NSCopying协议,如果让对象同时具备mutableCopy能力,同样要遵守NSMutableCopying协议,所以对于YCTeacherShowUserInfoModel来说,应该:

    #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
    
    

    然后在调用的时候,只需要按照下面的姿势就可以了,就可以实现修改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 = @"呵呵呵";
        }];
    
    

    相关文章

      网友评论

          本文标题:记开发中一个问题,关于copy和mutableCopy

          本文链接:https://www.haomeiwen.com/subject/dyopqxtx.html