1.2 property 关键字 —— copy

2020-05-13  本文已影响0人  哈库呐玛塔塔__

1.什么时候使用copy。

copy修饰的是不可变的对象。即使后边声明的是NSMutableXXX ,它实际上的真实数据类型也是不可变的。这时候对其进行操作就会崩溃了。

copy用作浅拷贝,只拷贝对象的指针,对象的内存是不变的。只是新开辟了一块指针类型的内存空间,这个内存空间里的内容是指向这个对象的指针。

通常情况下,当我们定义属性的时候,我们想要的是一个不可变的对象的时候。比如NSString,NSArray。

当我们给这个不可变的对象赋值的时候,要分两种情况考虑。

@property (nonatomic, copy) NSString *copyedString;

@property (nonatomic, strong) NSString * strongString;

①所赋的值对象也是不可变的。 

    NSString *string = @"123asd";

    self.copyedString = string;

    self.strongString = string;

    NSLog(@"stringP = %p ",string);

    NSLog(@"self.copyedStringP = %p  self.copyedString class = %@", self.copyedString, [self.copyedString class]);

    NSLog(@"self.strongStringP = %p  self.strongString class = %@", self.strongString, [self.strongString class]);

运行结果:

 stringP = 0x10e4f9078

 self.copyedStringP = 0x10e4f9078  self.copyedString class = __NSCFConstantString

 self.strongStringP = 0x10e4f9078  self.strongString class = __NSCFConstantString

    ②所赋的值对象是可变的。

    NSString *string = @"123asd".mutableCopy;

    self.copyedString = string;

    self.strongString = string;

    NSLog(@"stringP = %p ",string);

    NSLog(@"self.copyedStringP = %p  self.copyedString class = %@", self.copyedString, [self.copyedString class]);

    NSLog(@"self.strongStringP = %p  self.strongString class = %@", self.strongString, [self.strongString class]);

运行结果:

 stringP = 0x600001e9b4e0

 self.copyedStringP = 0xc862b1052a14edfe  self.copyedString class = NSTaggedPointerString

 self.strongStringP = 0x600001e9b4e0     self.strongString class = __NSCFString

当是第一种情况的时候其实strong和copy是没有区别的,_str的指针地址都一样,二者都是对string的引用计数加了1.

但是第二种情况的时候用strong修饰,和第一种情况仍然一样,引用计数加1,但此时虽然声明是NSString,但是strongString是对string这个可变字符串变量的一次持有,实际上strongString指向的就是这个可变的字符串,所以现在的strongString并不是不可变的字符串了。而copyedString不一样,copy时string的内存空间是可变的,与copyedString声明的所有权修饰符copy并不符合,所以此时需要做深拷贝,拷贝了内容,放在一块新的内存不可变的地址中去。

2.一种错误的使用情况

当 copy 修饰可变类型集合(例如:NSMutableArray)时,赋值后,会导致可变类型属性变为不可变类型,然后在调用可变类型方法时,会产生异常错误。

产生异常的原因是 copy 属性在运行时赋值时调用了 -copyWithZone:赋值,将可变类型转换为不可变类型。

3.一道题

所以表面上self.array是NSArray对象, 其实骨子里是NSMutableArray对象.这样的话将会对后期DEBUG增加很大的成本, 可能会导致莫名其妙的错误.

上一篇 下一篇

猜你喜欢

热点阅读