先来看一段代码,数据来源是不可变(immutable)的。
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong) NSArray *aStrongArr;
@property (nonatomic, copy) NSArray *aCopyArr;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSArray*immutableArr = [NSArrayarrayWithObjects:@"a",@"b",@"c", nil];
NSLog(@"retain count = %ld",CFGetRetainCount((__bridgeCFTypeRef)immutableArr));
NSLog(@"pointer = %p",immutableArr);
self.aCopyArr= immutableArr;
NSLog(@"retain count = %ld",CFGetRetainCount((__bridgeCFTypeRef)immutableArr));
NSLog(@"pointer = %p",self.aCopyArr);
self.aStrongArr= mutableArr;
NSLog(@"retain count = %ld",CFGetRetainCount((__bridgeCFTypeRef)immutableArr));
NSLog(@"pointer = %p",self.aStrongArr);
}
@end
输出结果为:
2018-11-08 16:13:41.066856+0800 OC-Swift[5284:191123] retain count = 2
2018-11-08 16:13:42.068732+0800 OC-Swift[5284:191123] pointer = 0x60000241eaf0
2018-11-08 16:13:43.540674+0800 OC-Swift[5284:191123] retain count = 3
2018-11-08 16:13:44.191545+0800 OC-Swift[5284:191123] pointer = 0x60000241eaf0
2018-11-08 16:13:45.860397+0800 OC-Swift[5284:191123] retain count = 4
2018-11-08 16:13:47.925061+0800 OC-Swift[5284:191123] pointer = 0x60000241eaf0
再来看一段代码,数据来源是可变(mutable)的。
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong) NSArray *aStrongArr;
@property (nonatomic, copy) NSArray *aCopyArr;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSMutableArray*mutableArr = [NSMutable ArrayarrayWithObjects:@"a",@"b",@"c", nil];
NSLog(@"retain count = %ld",CFGetRetainCount((__bridgeCFTypeRef)mutableArr));
NSLog(@"pointer = %p",mutableArr);
self.aCopyArr= mutableArr;
NSLog(@"retain count = %ld",CFGetRetainCount((__bridgeCFTypeRef)mutableArr));
NSLog(@"pointer = %p",self.aCopyArr);
self.aStrongArr= mutableArr;
NSLog(@"retain count = %ld",CFGetRetainCount((__bridgeCFTypeRef)mutableArr));
NSLog(@"pointer = %p",self.aStrongArr);
[mutableArraddObject:@"d"];
NSLog(@"%@",mutableArr);
NSLog(@"%@",self.aStrongArr);
NSLog(@"%@",self.aCopyArr);
}
@end
输出结果是:
2018-11-08 16:19:55.779050+0800 OC-Swift[5366:194115] retain count = 2
2018-11-08 16:19:55.779248+0800 OC-Swift[5366:194115] pointer = 0x60000231aaf0
2018-11-08 16:19:55.779355+0800 OC-Swift[5366:194115] retain count = 2
2018-11-08 16:19:55.779429+0800 OC-Swift[5366:194115] pointer = 0x60000231aa60
2018-11-08 16:19:55.779509+0800 OC-Swift[5366:194115] retain count = 3
2018-11-08 16:19:55.779587+0800 OC-Swift[5366:194115] pointer = 0x60000231aaf0
2018-11-08 16:19:55.779738+0800 OC-Swift[5366:194115] (
a, b,c, d
)
2018-11-08 16:19:55.779837+0800 OC-Swift[5366:194115] (
a, b,c, d
)
2018-11-08 16:19:55.779962+0800 OC-Swift[5366:194115] (
a, b,c
)
从上面的例子可以看出,当来源数据是NSArray(immutable),由于源数据是不可变的,所以,不管是strong还是copy的对象,都是指向原对象,引用计数都增加了1,copy操作只是做了次浅拷贝。
当来源数据是NSMutableArray(mutable)时,strong只是增加了对源数据的引用计数,而copy则是对源数据做了次深拷贝,产生一个新的对象,且copy指向这个新的对象。
用途:
因为父类指针可以指向子类对象,使用 copy 的目的是为了让本对象的属性不受外界影响,使用 copy 无论给我传入是一个可变对象还是不可对象,我本身持有的就是一个不可变的副本.如果我们使用是 strong ,那么这个属性就有可能指向一个可变对象,如果这个可变对象在外部被修改了,那么会影响该属性。
copy 此特质所表达的所属关系与 strong 类似。然而设置方法并不保留新值,而是将其“拷贝” (copy)。 当属性类型为 NSString 时,经常用此特质来保护其封装性,因为传递给设置方法的新值有可能指向一个 NSMutableString 类的实例。这个类是 NSString 的子类,表示一种可修改其值的字符串,此时若是不拷贝字符串,那么设置完属性之后,字符串的值就可能会在对象不知情的情况下遭人更改。所以,这时就要拷贝一份“不可变” (immutable)的字符串,确保对象中的字符串值不会无意间变动。只要实现属性所用的对象是“可变的” (mutable),就应该在设置新属性值时拷贝一份。
所以,同样和NSString有可变子类的NSArray,NSDictionary,在声明时也应该使用copy描述。
小知识:@property (nonatomic,copy) NSMutableArray *array会出现什么问题
添加,删除,修改数组内的元素的时候,程序会因为找不到对应的方法而崩溃.因为 copy 就是复制一个不可变 NSArray 的对象。
所以修饰可变的(NSMutableArray、NSMutableDictionary、NSMutableString)对象是不用copy,要用strong。
网友评论