copy 和mutableCopy 这种老生常谈的问题,还是得掰扯掰扯
之前在我们的意识当中 copy 和mutableCopy 就是 “深拷贝和浅拷贝”的概念,解释来说就是 深拷贝就是会开辟新的空间,浅拷贝就是拷贝的指针。
问题1:浅拷贝的以后修改原来的值,会影响到拷贝值吗?
走个例子看看
- string
(lldb) p str
(__NSCFConstantString *) $0 = 0x0000000100004038 @"demo"
(lldb) p strCopy
(__NSCFConstantString *) $1 = 0x0000000100004038 @"demo"
(lldb) p strMutableCopy
(__NSCFString *) $2 = 0x0000000103850b50 @"demo"
(lldb)
真的是 copy 只拷贝了指针,而mutableCopy 从新开辟了内存空间
那么我们赋值试一试
(__NSCFConstantString *) $0 = 0x00000001000040b8 @"newDemo"
(lldb) p strCopy
(__NSCFConstantString *) $1 = 0x0000000100004038 @"demo"
(lldb) p strMutableCopy
(__NSCFString *) $2 = 0x000000010074bd30 @"demo"
奇怪的知识又增加啦,对被复制的字符串 赋新值了,发现并没有影响到浅拷贝的值。
那就扒开PG看新裤子
- (id)copy {
return [(id)self copyWithZone:nil];
}
继续扒
+ (id)copyWithZone:(struct _NSZone *)zone {
return (id)self;
}
扒开不动了。
GPerson *person = [GPerson alloc];
person.name = @"AA";
NSArray *arr = @[person,person,person];
NSArray *arr1 = [arr copy];
NSMutableArray *arr2 = [arr mutableCopy];
打印结果
(lldb) p arr
(__NSArrayI *)1 = 0x00006000021907b0 @"3 elements"
(lldb) parr 2
Enter expressions, then terminate with an empty line to evaluate:
1
(lldb) p arr2
(__NSArrayM *) $2 = 0x00006000021907e0 @"3 elements"
所以由此可以观察到
copy 过后的 都是 不可变类型
mutableCopy 过后的 都是可变类型
NSString 为什么用copy 修饰呢
我们脑子里面都有一个 因为copy 修饰后,一旦赋值的话 不像strong修饰的那样复制对象的指针,然后 指向同一个 内存空间,但是当我们用copy 以及strong 修饰string 然后给string 赋值的时候,发现,不论我们怎么修改 赋值对象的时候都不影响到被赋值对象的值,如图;
@interface GPerson : NSObject
@property (nonatomic,copy)NSString *name;
@property (nonatomic,strong)NSString *des;
@end
GPerson *person = [GPerson alloc];
NSString *name = @"小王";
NSString *des = @"小王很厉害";
person.name = name;
person.des = des;
name = @"小王和老王";
des = @"王还是老的辣";
打印结果
(lldb) p person.name
(__NSCFConstantString *)1 = 0x00000001079a3188 @"小王很厉害"
(lldb) p person.name
(__NSCFConstantString *)3 = 0x00000001079a3188 @"小王很厉害"
都是不可变的情况下 copy 和strong 的时候 情况一致
但是有一种情况不同,因为nsmutablestring 是 string的子类,所以string类型的对象可以直接接收nsmutablestring 的对象。那咱们去试试
(lldb) p person.name
(__NSCFString *)1 = 0x0000600001244d50 @"小王好厉害的呢"
(lldb) p person.name
(__NSCFString *)3 = 0x0000600001244d50 @"小王好厉害的呢小刘不如 小王厉害"
终于找到copy 存在的意义了,就是怕可变数据 用strong 以后值会容易被改动
block 为啥用 copy
其实追溯到MRC 时期,当时 block是在栈中的,用copy 会拷贝到 堆中,但是ARC的时候系统已经智能了,聪明的大脑已经占领高地了,已经可以自动复制过去了。
网友评论