iOS 关于copy与mutablecopy的区别、copy与strong的区别

问题:
1.copy与mutablecopy的区别是什么
2.copy与strong的区别是什么
3.不可变对象(如NSString)用copy修饰还是strong修饰,
可变对象(如NSMutableString)用copy修饰还是strong修饰

copy、mutablecopy、strong这三个概念早就接触了,但是理解的一直都不深刻,现在,有必要重新整理一下。

答案:
1.copy:对不可变对象copy是浅拷贝,对可变对象copy是深拷贝
mutableCopy:一定是深拷贝
深拷贝时,copy出的是不可变类型,mutablecopy出的是可变类型
2.copy会开辟新内存复制一份新的数据,strong只是对象的引用计数加1
3.不可变对象用copy修饰,可变对象用strong修饰

另外:要实现自定义对象copy,需遵守NSCopying、NSMutableCopying协议,实现copyWithZone、mutableCopyWithZone 方法

是不是有点晕了,下面举个例子分析一下:

NSMutableArray *arr = [NSMutableArray arrayWithObjects:@"a", @"b", nil];
[arr addObject:@"!"];
NSLog(@"%@ ----- %@ ----- %@", [arr class], [[arr copy] class], [[arr mutableCopy] class]);
NSLog(@"%p ==== %p ==== %p",arr, [arr copy], [arr mutableCopy]);

NSArray *arr2 = [NSArray arrayWithObjects:@"a", @"b", nil];
NSLog(@"%@ ----- %@ ----- %@", [arr2 class], [[arr2 copy] class], [[arr2 mutableCopy] class]);
NSLog(@"%p ==== %p ==== %p",arr2, [arr2 copy], [arr2 mutableCopy]);
2018-04-23 11:59:21.922827+0800 iyuba[2204:86964] __NSArrayM ----- __NSArrayI ----- __NSArrayM
2018-04-23 11:59:21.922945+0800 iyuba[2204:86964] 0x604000447ce0 ==== 0x6040004400f0 ==== 0x60400025fbf0
2018-04-23 11:59:21.923060+0800 iyuba[2204:86964] __NSArrayI ----- __NSArrayI ----- __NSArrayM
2018-04-23 11:59:21.923375+0800 iyuba[2204:86964] 0x604000432860 ==== 0x604000432860 ==== 0x6040004400f0

第一行:可变对象copy后生成的是不可变类型,mutablecopy后生成的是可变类型
第二行:可变对象copy后产生了新的对象,mutablecopy后产生了新的对象
第三行:不可变对象copy后还是不可变类型,mutablecopy后生成的是可变类型
第四行:不可变对象copy后没有产生新的对象,mutablecopy后产生新的对象

总结一:可变对象copy产生新对象(深拷贝),对象是不可变类型,mutablecopy产生新对象(深拷贝),对象是可变类型;不可变对象copy没有产生新对象(浅拷贝),mutablecopy产生新对象(深拷贝),对象是可变类型。

是不是对应了上边的答案呢。下面来看用copy与strong修饰对象时的区别:

#import <Foundation/Foundation.h>

@interface Person : NSObject

@property (nonatomic, copy) NSString *name;

@end
Person *person = [[Person alloc] init];
person.name = string;

[string appendString:@"--修改过的名字"];

NSLog(@"name = %@", person.name);
NSLog(@"%p ----- %p", string, person.name);
2018-04-23 11:59:21.923686+0800 iyuba[2204:86964] name = 我是名字
2018-04-23 11:59:21.923851+0800 iyuba[2204:86964] 0x6040004400f0 ----- 0x6040004323c0

实际赋值是这样的

- (void)setName:(NSString *)name
{
    _name = [name copy];
}

从上面的结论可以得到,copy不论深浅拷贝,结果一定是不可变的,所以name值是不会变的。

但是若用strong修饰name

@property (nonatomic, strong) NSString *name;
2018-04-23 12:09:53.585089+0800 iyuba[2323:93298] name = 我是名字--修改过的名字

name时会跟着变化的,原因是strong是强引用,使name成为一个指针指向了string对象。
总结二:strong使我们定义的NSString类型产生了不可控制的结果,所以对于不可变类型需要用copy来修饰。

同样的对于可变类型为什么用strong修饰呢,我们只需要看copy修饰会出现什么情况

@property (nonatomic, copy) NSMutableString *name;
    NSMutableString *string = [NSMutableString stringWithFormat:@"我是名字"];

    Person *person = [[Person alloc] init];
    person.name = string;
    [person.name appendString:@"--修改过的名字"];

    NSLog(@"name = %@", person.name);
    NSLog(@"%p ----- %p", string, person.name);

运行之后就会发现appendString崩溃,原因就是copy返回的是不可变的类型,所以是不能修改值的。
总结三:可变对象需要用strong修饰。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值