iOS开发之copy与mutableCopy

来源:互联网 发布:战龙三国孙策进阶数据 编辑:程序博客网 时间:2024/05/30 22:49

-copy与-mutableCopy都是NSObject类中的方法, 用来拷贝一个对象, 对象所属的类必须遵循NSCopying或者NSMutableCopying协议, 并且实现协议中的方法. -copy返回一个不可变的对象, 无论被拷贝的对象是不可变的(immutable)还是可变的(mutable), 而-mutableCopy则返回一个可变的对象.

读起来挺绕口的, 也很抽象, 这篇文章就结合实际代码来说明-copy和-mutableCopy的工作原理, 分为3部分来讲:

*非集合类对象的拷贝
*集合类对象的拷贝
*让自定义类支持拷贝功能

1.非集合类对象的拷贝(如NSString, NSData)
拷贝的方法有两种: -copy和-mutableCopy, 被拷贝的对象也有两种: 不可变的(immutable)和可变的(mutable), 所以就有4种情况, 下面分别来说明, 拿NSString为例.

(1)不可变对象 和 -copy方法:

NSString *str = @"string";NSString *cpy = [str copy];NSLog(@"%p %p", str, cpy);// 打印结果: 0x10e207088 0x10e207088

可以看到, str和cpy的指针是相同的, 也就是说, 对于不可变对象, -copy方法只进行了指针拷贝(或者说浅拷贝).

(2)可变对象 和 -copy方法:

NSMutableString *str = [NSMutableString stringWithFormat:@"mutable string"];NSString *cpy = [str copy];NSLog(@"%p %p", str, cpy);// 打印结果: 0x600000079b40 0x600000028360

str和cpy的指针不同, 说明对于可变对象, -copy方法重新开辟了一块内存, 进行了内容拷贝(或者说深拷贝). 另外需要注意的是, 虽然str是可变字符串, 但cpy却是不可变的, 因为-copy方法就是拷贝一个不可变的副本.

(3)不可变对象 和 -mutableCopy方法:

NSString *str = @"string";NSMutableString *cpy = [str mutableCopy];NSLog(@"%p %p", str, cpy);// 打印结果: 0x10614f088 0x600000269a40

进行了内容拷贝, 新对象cpy是个可变字符串.

(4)可变对象 和 -mutableCopy方法:

NSMutableString *str = [NSMutableString stringWithFormat:@"mutable string"];NSMutableString *cpy = [str mutableCopy];NSLog(@"%p %p", str, cpy);// 打印结果: 0x60000026a880 0x60000026a8c0

也是内容拷贝.

总结, 对于非集合类对象:
(1)不可变对象: -copy进行指针拷贝, -mutableCopy进行内容拷贝;
(2)可变对象: -copy和-mutableCopy都进行内容拷贝.

2.集合类对象的拷贝(如NSArray, NSDictionary)
依然分4种情况, 这次拿NSArray为例:

(1)不可变对象 和 -copy方法:

NSArray *arr = @[@"1", @"2", @"3"];NSArray *cpy = [arr copy];NSLog(@"%p %p", arr, cpy);// 打印结果: 0x600000241bf0 0x600000241bf0

可以看到, arr和cpy的指针是相同的, 也就是说, 对于不可变数组, -copy方法也只进行了指针拷贝(浅拷贝).

(2)可变对象 和 -copy方法:

NSMutableArray *arr = [NSMutableArray arrayWithObjects:@"1", @"2", @"3", nil];NSArray *cpy = [arr copy];NSLog(@"%p %p", arr, cpy);// 打印结果: 0x600000046e70 0x600000046d80

arr和cpy的指针不同, 说明进行了内容拷贝. 当然需要注意的是, 虽然arr是可变数组, 但cpy却是不可变的. 我们再来打印一下两个数组内所有元素的指针:

for (int i = 0; i < 3; i++) {    NSLog(@"arr[%d]: %p cpy[%d]: %p", i, arr[i], i, cpy[i]);}// 打印结果:// arr[0]: 0x102555088 cpy[0]: 0x102555088// arr[1]: 0x1025550a8 cpy[1]: 0x1025550a8// arr[2]: 0x1025550c8 cpy[2]: 0x1025550c8

发现了什么呢? 是的! cpy数组内所有元素的指针与arr数组相同. 也就是说, 虽然数组对象是内容拷贝, 但是数组内的元素却是指针拷贝.

(3)不可变对象 和 -mutableCopy方法:

NSArray *arr = @[@"1", @"2", @"3"];NSMutableArray *cpy = [arr mutableCopy];NSLog(@"%p %p", arr, cpy);// 打印结果: 0x60000004b8e0 0x60000004b340

进行了内容拷贝, 新对象cpy是个可变数组. 再次打印两个数组内所有元素的指针, 会发现各个元素依然是指针拷贝.

(4)可变对象 和 -mutableCopy方法:

NSMutableArray *arr = [NSMutableArray arrayWithObjects:@"1", @"2", @"3", nil];NSMutableArray *cpy = [arr mutableCopy];NSLog(@"%p %p", arr, cpy);// 打印结果: 0x600000047e30 0x600000047a10

结果同(3).

总结, 对于集合类对象:
(1)不可变对象: -copy进行指针拷贝, -mutableCopy进行内容拷贝, 而数组内的元素进行指针拷贝;
(2)可变对象: -copy和-mutableCopy都进行内容拷贝, 而数组内的元素进行指针拷贝.

3.让自定义类支持拷贝功能

其实很简单, 只需两步:
1.遵循NSCopying协议;
2.实现协议中的-copyWithZone:方法.
至于NSMutableCopying协议和-mutableCopyWithZone:方法, 本文就不做讨论了.

定义一个类, 遵循NSCopying协议:

@interface XYZPerson : NSObject <NSCopying>@property (nonatomic, copy) NSString *name;     // 姓名@property (nonatomic, copy) NSString *number;   // 手机号@end

实现-copyWithZone:方法:

@implementation XYZPerson- (NSString *)description {    return [NSString stringWithFormat:@"address: %p, name: %@, number: %@", self, self.name, self.number];}- (id)copyWithZone:(NSZone *)zone {    XYZPerson *cpy = [[[self class] allocWithZone:zone] init];    cpy.name = self.name;    cpy.number = self.number;    return cpy;}@end

至此, 一个最简单的拷贝功能就完成了, 验证一下:

XYZPerson *p1 = [[XYZPerson alloc] init];p1.name = @"Jack";p1.number = @"12345678";NSLog(@"%@", p1);XYZPerson *p2 = [p1 copy];NSLog(@"%@", p2);p1.name = @"Rose";p1.number = @"23456789";NSLog(@"%@", p1);NSLog(@"%@", p2);// 打印结果:// address: 0x60800003c100, name: Jack, number: 12345678// address: 0x60800003bf20, name: Jack, number: 12345678// address: 0x60800003c100, name: Rose, number: 23456789// address: 0x60800003bf20, name: Jack, number: 12345678

可以看到, -copy方法重新开辟了一块内存来存放p2对象, 它和p1是互相独立的, 后期修改p1的属性值, 并不会影响到p2, 反之亦然.

阅读全文
0 0
原创粉丝点击