ios 深浅拷贝的区别
深拷贝:对象拷贝,会产生新对象,引用计数+1;
浅拷贝:指针拷贝,不会产生新对象,引用计数不变;
深浅拷贝的判断依据:A:查看原来变量和拷贝的变量是否是同一个内存地址;B:或者去改变原来变量和拷贝变量其中一个的相关属性值,去看另外一个变量是否会发生变化;
系统原生对象深浅拷贝的区别
1.NSObject 类提供了copy 和mutableCopy方法,通过这两个方法即可拷贝已有对象的副本;
2.系统原生对象:NSString 和NSMutableString、NSArray 和NSMutableArray、NSDictionary和NDMutableDictionary、NSSet和NSMutableSet等,这些对象都遵循了NSCopying,NSMutableCopying协议NSValue、NSNumber只遵循了NSCopying协议。
3.不可变类型通过copy之后,是浅拷贝,mutableCopy之后是深拷贝;可变类型通过copy和mutableCopy之后都是深拷贝;无论是可变类型还是不可变类型,copy 之后都是不可变类型;
自定义对象拷贝
实际开发中我们也常会用到自定义对象拷贝;
对自定义对象进行copy,对象必须实现copy 的相关协议(NSCopying或者NSMutableCopy),否则会报错;例如:-[Person copyWithZone:]: unrecognized selector sent to instance 0x1c4030900
copy事例:
自定义Person类具有name,age,dog属性
@interface Dog : NSObject
@property(nonatomic,copy)NSString *color;
@end
@interface Person : NSObject
@property(nonatomic,copy)NSString *name;
@property(nonatomic,copy)NSString *age;
@property(nonatomic,strong)Dog *dog;
@end
以上代码Person类并不具备copy 功能,当我们对其使用copy方法就会报错:[Person copyWithZone:]: unrecognized selector sent to instance 0x1c4030900;
要让Person具备copy 功能必须让其遵循NSCopying协议,并且实现该协议;
#import "Person.h"
@implementation Person
- (nonnull id)copyWithZone:(nullable NSZone *)zone {
Person *per = [[[self class] allocWithZone:zone]init];
per.name = self.name;
per.age = self.age;
//dog 是一个对象,用这种方法并不是完全的深拷贝,
//拷贝之后的对象和原对象共同拥有一个dog
//要达到完全深拷贝,让Dog 也实现copy协议并且代码改为 per.dog = [self.dog copy];
// per.dog = self.dog;
Dog *dog = [[Dog alloc]init];
dog.color = self.dog.color;
self.dog = dog;
return per;
}
@end
综上述:要让一个自定对象具有拷贝功能,那么该对象必须实现NSCopying协议或者NSMutableCopying协议;当对象调用copy或者mutableCopy方法的时候,系统会触发协议中的方法
@protocol NSCopying
- (id)copyWithZone:(nullable NSZone *)zone;
@end
@protocol NSMutableCopying
- (id)mutableCopyWithZone:(nullable NSZone *)zone;
@end
验证copy 的常用方法
将原对象地址和copy之后的对象地址作比较
// 内存地址一样为浅拷贝,内存地址不一样的为深拷贝
//原对象
NSArray *arr = [NSArray array];
NSMutableArray *mut = [NSMutableArray array];
//拷贝案例
NSArray *copyArr = arr.copy; //不可变数组的copy
NSLog(@"arr:%p--copyArr:%p",arr,copyArr); //查看内存地址是否一样
NSArray *mutcopyArr = arr.mutableCopy;//不可变数组的mutableCopy
NSLog(@"arr:%p--mutcopyArr:%p",arr,mutcopyArr); //查看内存地址是否一样
NSMutableArray *copyMut = mut.copy; //可变数组的copy
NSLog(@"mut:%p--copyMut:%p",mut,copyMut);//查看内存地址是否一样
NSMutableArray *mutableCopyMut = mut.mutableCopy; //可变数组的mutableCopy
NSLog(@"mut:%p--mutableCopyMut:%p",mut,mutableCopyMut);//查看内存地址是否一样
Demo