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

2017-06-16  本文已影响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数组中模型的值了。

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

基于上面的结论,浅复制,并不拷贝对象本身,仅仅是拷贝指向对象的指针;深复制是直接拷贝整个对象内存到另一块内存中。所以我们应该让对象具备深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 = @"呵呵呵";
    }];

上一篇下一篇

猜你喜欢

热点阅读