copy:
copy/mutableCopy 是通过NSCopying/NSMutableCopying实现的
浅/深copy(区别: 原对象和副本的指针是不是指向同一地址)
浅复制:复制对象的指针,两个指针指向同一个对象。
深复制:复制对象本身, 复制后的对象和被复制的对象相互独立,互补影响。
修饰关键字 copy
可以copy的对象都遵守NSCopying/NSMutableCopying
NSCopying/NSMutableCopying 协议方法
NSZone
//NSCopying
- (id)copyWithZone:(nullable NSZone *)zone;
//NSMutableCopying
- (id)mutableCopyWithZone:(nullable NSZone *)zone;
//对象的复制方法
-(id)copy;
-(id)mutableCopy;
深/浅copy
容器类(容器中存放对象的指针需区分对待)和其他类
其他对象:
NSString string类型在许多语言中都被特殊处理
NSString *string1 = [NSString stringWithFormat:@"string1"];
NSString *string2 = string1.copy;
NSMutableString *string3 = string1.mutableCopy;
NSLog(@"string1 : %@ %@, %p", string1.class, string1, string1);
NSLog(@"string2 : %@ %@, %p", string2.class, string2, string2);
NSLog(@"string3 : %@ %@, %p", string3.class, string3, string3);
NSString
string1和string2地址是同一个 在NSString中copy是浅copy
string3是重新传家的地址 在NSString中mutableCopy是深copy
插入一个知识点
__NSCFConstantString, __NSCFString, NSTaggedPointerString,
__NSCFConstantString 是字符串常量 app生命周期结束前不会释放
//创建方式
NSString *string = @"123";
__NSCFString 是NSString的子类,和普通类型一样受系统内存回收机制管理
//创建方式
NSString *string = [NSString stringWithFormat:@"string1"];
NSTaggedPointerString
标签指针类型,内部优化 在64位系统中指针在内存中的大小是8位,可以存放一些比较小的字符串;系统会根据string的大小来自动创建NSTaggedPointerString,就是当string长度小于9位创建的类型是NSTaggedPointerString,长度大于9是__NSCFString。(9是自己测试出来的,没有具体的文档描述);
NSMutableString
NSMutableString *string1 = [NSMutableString stringWithFormat:@"string"];
NSString *string2 = string1.copy;
NSMutableString *string3 = string1.mutableCopy;
NSLog(@"string1 : %@ %@, %p", string1.class, string1, string1);
NSLog(@"string2 : %@ %@, %p", string2.class, string2, string2);
NSLog(@"string3 : %@ %@, %p", string3.class, string3, string3);
NSMutableString
copy/mutableCopy 都是深copy
继承自NSObject的类(需要遵守NSCopying协议)
//浅copy
#import "copyObject.h"
@implementation copyObject
-(id)copyWithZone:(NSZone *)zone{
return self;
}
@end
//深copy
#import "copyObject.h"
@implementation copyObject
-(id)copyWithZone:(NSZone *)zone{
copyObject *object = [[copyObject alloc]init];
object.name = @"object";
return object;
}
@end
容器类
NSArray
NSObject *object1 = [[NSObject alloc]init];
NSObject *object2 = [[NSObject alloc]init];
NSObject *object3 = [[NSObject alloc]init];
NSArray *array1 = @[object1, object2, object3];
NSArray *array2 = array1.copy;
NSMutableArray *array3 = array1.mutableCopy;
NSLog(@"array1 : %@ %@, %p", array1.class, array1, array1);
NSLog(@"array2 : %@ %@, %p", array2.class, array2, array2);
NSLog(@"array3 : %@ %@, %p", array3.class, array3, array3);
__NSarrayI 不可变数组 __NSArrayM可变数组
NSArray
copy 浅copy
MutableCopy 深copy
数组中的元素并没有copy
NSMutableArray
NSObject *object1 = [[NSObject alloc]init];
NSObject *object2 = [[NSObject alloc]init];
NSObject *object3 = [[NSObject alloc]init];
NSMutableArray *array1 = [NSMutableArray array];
[array1 addObject:object1];
[array1 addObject:object2];
[array1 addObject:object3];
NSArray *array2 = array1.copy;
NSMutableArray *array3 = array1.mutableCopy;
NSLog(@"array1 : %@ %@, %p", array1.class, array1, array1);
NSLog(@"array2 : %@ %@, %p", array2.class, array2, array2);
NSLog(@"array3 : %@ %@, %p", array3.class, array3, array3);
NSMutableArray
copy/mutableCopy 都是深copy
数组中的元素并没有copy
修饰关键字 copy
在原对象不可变的情况下 使用copy/strong修饰并没有差别
在原对象为可变的情况下
修饰不可变对象
//声明
@property (nonatomic, copy) NSString *nameCopy;
@property (nonatomic, strong) NSString *nameStrong;
//操作
NSMutableString *string = [NSMutableString stringWithFormat:@"name"];
self.nameStrong = string;
self.nameCopy = string;
[string appendString:@"a"];
NSLog(@"string : %@ %@, %p", string.class, string, string);
NSLog(@"self.nameCopy : %@ %@, %p", self.nameCopy.class, self.nameCopy, self.nameCopy);
NSLog(@"self.nameStrong : %@ %@, %p", self.nameStrong.class, self.nameStrong, self.nameStrong);
strong 修饰不可变对象 和 原对象指向同一地址,随着原对象改变而改变 (数据不稳定)
copy修饰不可变对象 copy一份 原对象改变不影响 copy的对象
修饰可变对象
使用strong和copy修饰和修饰不可变对象一样 strong修饰指向同一地址 copy修饰创建新对象
NSMutableString *string = [NSMutableString stringWithFormat:@"name"];
self.nameStrong = string;
self.nameCopy = string;
[string appendString:@"a"];
NSLog(@"string : %@ %@, %p", string.class, string, string);
NSLog(@"self.nameCopy : %@ %@, %p", self.nameCopy.class, self.nameCopy, self.nameCopy);
NSLog(@"self.nameStrong : %@ %@, %p", self.nameStrong.class, self.nameStrong, self.nameStrong);
注意 self.nameCopy 类型由NSMutableString-> NSString
一般很少使用NSMutableString;在NSMutableArray上也是类似,如果对NSMutableArray使用copy有可能导致类型变为NSArray,进而进行增删改功能导致crash。
block 修饰
block 是被创建在栈上的
ARC copy和strong修饰 block 都会被从栈区复制到堆区
MRC copy会把block从栈区复制到堆区并且对block中使用的外部对象进行retain操作
retain并不会保存在block中使用的外部对象,当超出block所在的作用域时,调用block, block使用外部对象(此时若对象已被释放)是会造成crash。
个人知识记录