iOS copy 和 mutableCopy

2021-08-18  本文已影响0人  唱歌的鼻涕泡
copy 和mutableCopy 这种老生常谈的问题,还是得掰扯掰扯

之前在我们的意识当中 copy 和mutableCopy 就是 “深拷贝和浅拷贝”的概念,解释来说就是 深拷贝就是会开辟新的空间,浅拷贝就是拷贝的指针。

问题1:浅拷贝的以后修改原来的值,会影响到拷贝值吗?

走个例子看看

(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 *) 0 = 0x00006000021907b0 @"3 elements" (lldb) p arr1 (__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 *) 0 = 0x00000001079a3168 @"小王" (lldb) p person.des (__NSCFConstantString *)1 = 0x00000001079a3188 @"小王很厉害"
(lldb) p person.name
(__NSCFConstantString *) 2 = 0x00000001079a3168 @"小王" (lldb) p person.des (__NSCFConstantString *)3 = 0x00000001079a3188 @"小王很厉害"

都是不可变的情况下 copy 和strong 的时候 情况一致

但是有一种情况不同,因为nsmutablestring 是 string的子类,所以string类型的对象可以直接接收nsmutablestring 的对象。那咱们去试试

(lldb) p person.name
(__NSCFString *) 0 = 0x0000600001c19e80 @"小王" (lldb) p person.des (__NSCFString *)1 = 0x0000600001244d50 @"小王好厉害的呢"
(lldb) p person.name
(__NSCFString *) 2 = 0x0000600001c19e80 @"小王" (lldb) p person.des (__NSCFString *)3 = 0x0000600001244d50 @"小王好厉害的呢小刘不如 小王厉害"

终于找到copy 存在的意义了,就是怕可变数据 用strong 以后值会容易被改动

block 为啥用 copy

其实追溯到MRC 时期,当时 block是在栈中的,用copy 会拷贝到 堆中,但是ARC的时候系统已经智能了,聪明的大脑已经占领高地了,已经可以自动复制过去了。

上一篇 下一篇

猜你喜欢

热点阅读