首先我們先看一段代碼,
這是一個模型,里面有四個屬性
@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 = @"呵呵呵";
}];