# OC中的copy和strong修饰符

626 阅读3分钟

以前在oc中,如果一个属性比如NSArray,如果使用copy来修饰,则是不可变的.


@property (nonatomic, copy) NSMutableArray *nmArray;

当给nmArray赋值一个可变的数组对象时,用copy修饰则代表它会进行一次copy操作,则变为不可变对象.


NSMutableArray *arr = [NSMutableArray arrayWithArray:@[@"1", @"2"]];
_nmArray = arr;
[_nmArray removeLastObject];
NSLog(@"nmArray = %@", _nmArray);

这段代码在以前的oc中是会造成crash的,因为不可变的数组是不能操作的.

但是现在试了一下,并不会造成crash._nmArray还是可以进行增删的操作.

查看_nmArray的内存地址,发现copy和strong一样,都是只拷贝了指针的浅拷贝.


// 声明
@property (nonatomic, copy) NSMutableArray *nmCopyArray;
@property (nonatomic, strong) NSMutableArray *nmStrongArray;

// 赋值
NSMutableArray *arr = [NSMutableArray arrayWithArray:@[@"1", @"2"]];
_nmCopyArray = arr;
_nmStrongArray = arr;
[arr removeLastObject];
NSLog(@"arr = 指针 %p 内存 %p", &arr, arr);
NSLog(@"nmArray = 指针 %p 内存 %p", &_nmCopyArray, _nmCopyArray);
NSLog(@"nmStrongArray = 指针 %p 内存 %p", &_nmStrongArray, _nmStrongArray);

// 打印
arr = 指针 0x7ffee5db6020 内存 0x6000015430c0
nmArray = 指针 0x7fac07f08940 内存 0x6000015430c0
nmStrongArray = 指针 0x7fac07f08948 内存 0x6000015430c0

有可能是OC的实现发生了改变;

数组的copy和mutableCopy

针对可变数组和不可变数组测试copy和mutableCopy:

不可变数组的copy是浅拷贝, mutableCopy是深拷贝

可变数组的copy和mutableCopy都是深拷贝,这和以前是一样的.

NSString的copy和mutableCopy

使用copy修饰的NSString属性,当赋值了一个NSMutableString时,也是进行了浅拷贝,这使得copy和strong基本没有区别的.


// 声明
@property (nonatomic, copy) NSString *copyname;
@property (nonatomic, strong) NSString *strongName;

// 赋值
NSMutableString *nmStr = [[NSMutableString alloc]initWithString:@"zhang"];
_copyname = nmStr;
_strongName = nmStr;
NSLog(@"nmStr - %@ - 指针 %p - 地址 %p", nmStr, &nmStr, nmStr);
NSLog(@"copyname - %@  - 指针 %p - 地址 %p", _copyname, &_copyname, _copyname);
NSLog(@"strongname - %@  - 指针 %p - 地址 %p", _strongName, &_strongName, _strongName);
[nmStr appendString:@"san"];
NSLog(@"nmStr - %@ - 指针 %p - 地址 %p", nmStr, &nmStr, nmStr);
NSLog(@"copyname - %@  - 指针 %p - 地址 %p", _copyname, &_copyname, _copyname);
NSLog(@"strongname - %@  - 指针 %p - 地址 %p", _strongName, &_strongName, _strongName);

// 打印
nmStr - zhang - 指针 0x7ffeeedf0010 - 地址 0x600000936ee0
copyname - zhang  - 指针 0x7fdbca107780 - 地址 0x600000936ee0
strongname - zhang  - 指针 0x7fdbca107788 - 地址 0x600000936ee0

nmStr - zhangsan - 指针 0x7ffeeedf0010 - 地址 0x600000936ee0
copyname - zhangsan  - 指针 0x7fdbca107780 - 地址 0x600000936ee0
strongname - zhangsan  - 指针 0x7fdbca107788 - 地址 0x600000936ee0

以前认为copy属性是进行了一次 [str copy] 的深拷贝操作,str的引用计数不增加. 现在应该是只发生了浅拷贝,查看下引用计数:


NSLog(@"nmStr retaincount copy前 - %ld", CFGetRetainCount((__bridge CFTypeRef)(nmStr)));
NSString *string11 = [nmStr copy];
NSLog(@"string11 - %@ - 指针 %p - 地址 %p", string11, &string11, string11);
NSLog(@"nmStr retaincount copy后 - %ld", CFGetRetainCount((__bridge CFTypeRef)(nmStr)));

// 打印
nmStr retaincount copy前 - 3
string11 - zhangsan - 指针 0x7ffeeddd5018 - 地址 0xcb73896b9d84e74e
nmStr retaincount copy后 - 3

在对nmStr进行copy操作后,nmStr的引用计数没有增加,说明copy是深拷贝,后面的string11的地址也说明了这点.所以属性用copy修饰并不是深拷贝了.