copy和mutablecopy

ios提供了copy和mutablecopy方法,顾名思义,copy就是复制了一个imutable的对象,而mutablecopy就是复制了一个mutable的对象。以下将举几个例子来说明。

1、系统的非容器类对象:这里指的是NSString、NSNumber等等一类的对象。

    NSString *string1 = @"origion";
    NSLog(@"1的地址:%p", string1);
    
    NSString *stringCopy2 = [string1 copy];
    NSLog(@"2的地址:%p", stringCopy2);
    
    NSMutableString *stringMCopy3 = [string1 mutableCopy];
    NSLog(@"3的地址:%p", stringMCopy3);
    
    [stringMCopy3 appendString:@"!!"];
    NSLog(@"4的地址:%p", stringMCopy3);
    
    // 输出结果
    2015-03-26 10:40:11.397 Test[1139:55746] 1的地址:0x10d6c4050
    2015-03-26 10:40:11.398 Test[1139:55746] 2的地址:0x10d6c4050
    2015-03-26 10:40:11.398 Test[1139:55746] 3的地址:0x7fc411c3ae20
    2015-03-26 10:40:11.399 Test[1139:55746] 4的地址:0x7fc411c3ae20

查看内存可以发现,string1和string2指向的是同一块内存区域(又叫apple弱引用weak reference),此时string2的引用计数和string1的一样都为2。而string3则是我们所说的真正意义上的复制,系统为其分配了新内存,但指针所指向的字符串还是和string1所指的一样。

再看下面的例子:

    NSMutableString *string1 = [NSMutableString stringWithString: @"origion"];
    NSLog(@"1 的地址:%p", string1);
    
    NSString *string2 = [string1 copy];
    NSLog(@"2 的地址:%p", string2);
    
    NSMutableString *string3 = [string1 copy];
    NSLog(@"3 的地址:%p", string3);
    
    NSMutableString *string4 = [string1 mutableCopy];
    NSLog(@"4 的地址:%p", string4);
    
//    [string3 appendString:@"mm"];//error
    [string1 appendString:@" origion!"];
    [string4 appendString:@"!!"];
    NSLog(@"1 的结果:%@", string1);
    NSLog(@"4 的结果:%@", string4);
    // 输出结果
    2015-03-26 10:47:03.073 Test[1192:60641] 1 的地址:0x7fd22141f580
    2015-03-26 10:47:03.074 Test[1192:60641] 2 的地址:0x7fd221539b60
    2015-03-26 10:47:03.074 Test[1192:60641] 3 的地址:0x7fd22176c150
    2015-03-26 10:47:03.074 Test[1192:60641] 4 的地址:0x7fd221770dd0
    2015-03-26 10:47:03.074 Test[1192:60641] 1 的结果:origion origion!
    2015-03-26 10:47:03.074 Test[1192:60641] 4 的结果:origion!!

以上四个NSString对象所分配的内存都是不一样的。

但是对于string2其实是个imutable对象,所以上述会报错。

结论:
对于系统的非容器类对象,我们可以认为,如果对一不可变对象复制,copy是指针复制(浅拷贝)和mutableCopy就是对象复制(深拷贝)。如果是对可变对象复制,都是深拷贝,但是copy返回的对象是不可变的。


2、系统的容器类对象:指NSArray,NSDictionary等。对于容器类本身,上面讨论的结论也是适用的,需要探讨的是复制后容器内对象的变化。


//copy返回不可变对象,mutablecopy返回可变对象
NSArray *array1 = [NSArray arrayWithObjects:@"a",@"b",@"c",nil];
NSArray *arrayCopy1 = [array1 copy];
//arrayCopy1是和array同一个NSArray对象(指向相同的对象),包括array里面的元素也是指向相同的指针
NSLog(@"array1 retain count: %d",[array1 retainCount]);
NSLog(@"array1 retain count: %d",[arrayCopy1 retainCount]);
NSMutableArray *mArrayCopy1 = [array1 mutableCopy];
 //mArrayCopy1是array1的可变副本,指向的对象和array1不同,但是其中的元素和array1中的元素指向的是同一个对象。mArrayCopy1还可以修改自己的对象
[mArrayCopy1 addObject:@"de"];
[mArrayCopy1 removeObjectAtIndex:0];

array1和arrayCopy1是指针复制,而mArrayCopy1是对象复制,mArrayCopy1还可以改变期内的元素:删除或添加。但是注意的是,容器内的元素内容都是指针复制。
下面用另一个例子来测试一下。
    NSMutableArray *mArray1 = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c",nil];
    NSArray *mArrayCopy2 = [mArray1 copy];
    NSLog(@"mArray1 retain count: %lu",(unsigned long)[mArray1 retainCount]);
    NSMutableArray *mArrayMCopy1 = [mArray1 mutableCopy];
    NSLog(@"mArray1 retain count: %lu",(unsigned long)[mArray1 retainCount]);
    //mArrayCopy2,mArrayMCopy1和mArray1指向的都是不一样的对象,但是其中的元素都是一样的对象——同一个指针
    //一下做测试
    NSMutableString *testString = [mArray1 objectAtIndex:0];
    //testString = @"1a1";//这样会改变testString的指针,其实是将@“1a1”临时对象赋给了testString
    [testString appendString:@" tail"];//这样以上三个数组的首元素都被改变了"!!"];
    
    [mArray1 addObject:@"dddd"];
    [[mArrayMCopy1 objectAtIndex:0] appendString:@"---weixhe"];

    NSLog(@"%@", mArray1);
    NSLog(@"%@",mArrayCopy2 );
    NSLog(@"%@",mArrayMCopy1 );
    

    // 输出结果
    2015-03-26 10:50:14.194 Test[1216:62579] mArray1 retain count: 1
    2015-03-26 10:50:14.195 Test[1216:62579] mArray1 retain count: 1
    2015-03-26 10:50:14.195 Test[1216:62579] (
<span style="white-space:pre">	</span>"a tail---weixhe",
<span style="white-space:pre">	</span>b,
<span style="white-space:pre">	</span>c,
<span style="white-space:pre">	</span>dddd
    )
    2015-03-26 10:50:14.195 Test[1216:62579] (
<span style="white-space:pre">	</span>"a tail---weixhe",
<span style="white-space:pre">	</span>b,
<span style="white-space:pre">	</span>c
    )
    2015-03-26 10:50:14.196 Test[1216:62579] (
<span style="white-space:pre">	</span>"a tail---weixhe",
<span style="white-space:pre">	</span>b,
<span style="white-space:pre">	</span>c
    )

由此可见,对于容器而言,其元素对象始终是指针复制。如果需要元素对象也是对象复制,就需要实现深拷贝。





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Objective-C 中,深拷贝(Deep Copy)和浅拷贝(Shallow Copy)是用于复制对象的两种不同方式。 浅拷贝是指创建一个新的对象,该对象与原始对象共享数据的内存地址。换句话说,新对象只是原始对象的一个引用,对新对象的修改也会影响原始对象。在 Objective-C 中,可以使用 `copy` 方法来执行浅拷贝。 深拷贝是指创建一个新的对象,并且复制原始对象的所有数据。这意味着新对象有自己的内存地址,对新对象的修改不会影响原始对象。在 Objective-C 中,可以使用 `mutableCopy` 方法来执行深拷贝。 需要注意的是,深拷贝只会复制对象本身,而不会递归地复制对象所包含的其他对象。如果需要对对象的所有数据进行递归复制,可以通过实现 NSCopying 协议来自定义深拷贝操作。 下面是一个示例代码,演示了如何执行浅拷贝和深拷贝: ```objective-c #import <Foundation/Foundation.h> @interface Person : NSObject <NSCopying> @property (nonatomic, copy) NSString *name; @end @implementation Person - (instancetype)copyWithZone:(NSZone *)zone { Person *copy = [[Person allocWithZone:zone] init]; copy.name = self.name; return copy; } @end int main(int argc, const char * argv[]) { @autoreleasepool { Person *person1 = [[Person alloc] init]; person1.name = @"John"; // 浅拷贝 Person *person2 = [person1 copy]; NSLog(@"person1: %@, person2: %@", person1.name, person2.name); // 输出:person1: John, person2: John // 深拷贝 Person *person3 = [person1 mutableCopy]; person3.name = @"Emily"; NSLog(@"person1: %@, person3: %@", person1.name, person3.name); // 输出:person1: John, person3: Emily } return 0; } ``` 在上面的示例中,使用 `copy` 方法执行了浅拷贝操作,`mutableCopy` 方法执行了深拷贝操作。注意,为了实现深拷贝,我们在 `Person` 类中遵循了 NSCopying 协议,并重写了 `copyWithZone:` 方法来自定义深拷贝操作。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值