拷贝方法分两种:copy和muutableCopy
一般只有Foundation框架自带的一些类才具有区分可变/不可变的能力,如:字符串、数组、字典等。这些类在使用copy和muutableCopy时有区别,返回可能是可变/不可变的对象。
其他类不区分是否可变,如:自定义的类,UIKit框架下的类。这些类在使用copy和muutableCopy时没有区别,返回的都是可变对象。
区分可变/不可变的拷贝
区分可变/不可变的类有以下几种:
字符串:NSString NSMutableString
数组:NSArray NSMutableArray
字典:NSDictionary NSMutableDictionary
数据:NSData NSMutableData
集合:NSSet NSMutableSet
拷贝类型分深拷贝和浅拷贝
深拷贝:拷贝源对象生成副本对象,两者在不同的内存。对不可变类型调用mutableCopy、可变类型调用copy和mutableCopy都是深拷贝。
浅拷贝:不拷贝源对象,不会生成副本对象,只拷贝指向源对象的指针。对不可变对象调用copy方法的情况就是浅拷贝。
mutableCopy返回的是可变对象。
案例分析
1.copy
copy返回的是不可变对象
调用copy拷贝不可变对象例子:
NSDictionary *dic1 = @{@"key1":@"value1"};
NSDictionary *dic2 = [dic1 copy];
// 打印结果:0x10aeb37e8,0x10aeb37e8
// 两者地址相同,指向同一个对象,为浅拷贝
NSLog(@"%p,%p",dic1,dic2);
//修改dic2 报错崩溃 *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<NSConstantDictionary 0x10aeb37e8> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key key2.'
[dic2 setValue:@"value2" forKey:@"key2"];
调用copy拷贝可变对象例子:
NSMutableDictionary *dic1 = [NSMutableDictionary dictionaryWithObject:@"value1" forKey:@"key1"];
NSDictionary *dic2 = [dic1 copy];
// 打印结果:0x600001374060,0x6000013740a0,{ key1 = value1;},{key1 = value1;}
// 两者地址不同,内容相同,为深拷贝,返回的是不可变对象
NSLog(@"%p,%p,",dic1,dic2);
//修改dic2 报错崩溃 *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<__NSFrozenDictionaryM 0x60000079f760> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key key2.'
[dic2 setValue:@"value2" forKey:@"key2"];
2.mutableCopy
mutableCopy返回的是可变对象。
调用mutableCopy拷贝不可变对象例子:
NSDictionary *dic1 = @{@"key1":@"value1"};
NSDictionary *dic2 = [dic1 mutableCopy];
// 打印结果:0x105c9c7e8,0x600003ec5760,{key1 = value1;},{key1 = value1;}
// 两者地址不同,内容相同,为深拷贝
NSLog(@"%p,%p,%@,%@",dic1,dic2,dic1,dic2);
// 返回的是可变对象 修改dic2,修改成功
[dic2 setValue:@"value2" forKey:@"key2"];
调用mutableCopy拷贝可变对象例子:
NSMutableDictionary *dic1 = [NSMutableDictionary dictionaryWithObject:@"value1" forKey:@"key1"];
NSDictionary *dic2 = [dic1 mutableCopy];
// 打印结果:0x6000001109e0,0x600000110b20,{key1 = value1;},{key1 = value1;}
// 两者地址不同,内容相同,为深拷贝
NSLog(@"%p,%p,%@,%@",dic1,dic2,dic1,dic2);
// 返回的是可变对象 修改dic2,修改成功
[dic2 setValue:@"value2" forKey:@"key2"];
不区分可变/不可变的拷贝
其他类是不区分是否可变的,如:自定义类、UIKit框架下的类。
拷贝类型只有深拷贝,没有浅拷贝,使用copy和mutableCopy没有区别,返回的都是可变对象。使用时,需要先遵循NSCoping或NSMutableCopying协议。
@interface Person : NSObject<NSCopying,NSMutableCopying>
@property (nonatomic,copy) NSString * name;
@property (nonatomic,strong) NSMutableArray *maryDatas;
@end
@implementation Person
- (id)copyWithZone:(NSZone *)zone {
Person *person = [Person allocWithZone:zone];
person.name = self.name;
person.maryDatas = [self.maryDatas mutableCopy];
return person;
}
- (id)mutableCopyWithZone:(NSZone *)zone {
Person *person = [Person allocWithZone:zone];
person.name = self.name;
person.maryDatas = [self.maryDatas mutableCopy];
return person;
}
@end
// 示例:
- (void)test {
Person *person1 = [[Person alloc] init];
person1.name = @"jack";
person1.maryDatas = [NSMutableArray arrayWithObject:@"1"];
Person *person2 = [person1 copy];
person2.name = @"bela";
}
网友评论