NSString 为什么用 copy ? Block 为什么用
copy
深拷贝与浅拷贝的区别, 在于是否开辟新内存,copy 只针对堆内存对象而言。
浅拷贝:
拷贝的是地址,和对象的 = 赋值是一样的。
OC 中 我们声明一个 NSString 属性。
@property NSString *str;
为什么会有这个 *
, c 语言中,*
是取值操作符,*str
对应的是值, 所以 str
是* str
的地址, 为什么要说这个, 就是 = 传递的是对象的地址, 浅拷贝就是地址的拷贝.
提示:上面提到的只针对堆内存的对象。
& 取址操作符,平常声明的值变量是存在栈内存中.
int a = 5;
a 对应的栈中存放的 5,&a 对应栈内存地址。
深拷贝:
开辟新的内存空间,相当于声明了一个新的对象,对象中的值与当前对象值相同。
NSString 为什么用 copy ?
@property (nonatomic, strong) NSString *strongStr;
@property (nonatomic, copy) NSString *cpyStr;
我们有两个对象, 一个用 strong, 一个用 copy.
NSString *tmpStr = @"temp";
self.strongStr = tmpStr;
self.cpyStr = tmpStr;
2017-04-10 12:06:11.953 Copy[66625:4617737] tmpStr:temp
strongStr:temp
cpyStr:temp
2017-04-10 12:06:11.953 Copy[66625:4617737] tmpStr:0x10f096078
strongStr:0x10f096078
cpyStr:0x10f096078
对于不可变字符串, copy 和 strong 都是浅拷贝.
NSMutableString *tmpStr = [[NSMutableString alloc] initWithString:@"temp"];
self.strongStr = tmpStr;
self.cpyStr = tmpStr;
[tmpStr appendString:@" + add"];
NSLog(@"tmpStr:%@\n strongStr:%@\n cpyStr:%@", tmpStr, self.strongStr, self.cpyStr);
NSLog(@"tmpStr:%p\n strongStr:%p\n cpyStr:%p", tmpStr, self.strongStr, self.cpyStr);
2017-04-10 11:58:56.888 Copy[66562:4610424]
tmpStr:temp + add
strongStr:temp + add
cpyStr:temp
2017-04-10 11:58:56.888 Copy[66562:4610424] tmpStr:0x600000271580
strongStr:0x600000271580
cpyStr:0xa000000706d65744
当 tmpStr 改变之后 strongStr 也改变了, 虽然 strongStr 是个不可变字符串, 但是它指向了一个可变字符串. 可以看见 cpyStr 是深拷贝, 它指向的内存和 tmpStr 完全不同.
NSMutableString 不可以使用 copy.
@property (nonatomic, copy) NSMutableString *mutableString;
copy 返回的都是不可变的, 所以当执行 appendString:
等NSMutableString特有的方法的时候, 会报unrecognized selector sent to instance
这个错误.
tips:
为什么 NSString 可以直接指向一个常量, 而 NSMutableString 不可以?
不可变字符串, 不可变, 他可以指向一个常量, 常量是不可变的, 存放在常量区.
Block 为什么用 copy?
代码块 是存在栈区的, 需要通过 copy 拷贝到堆内存, ARC 下, 赋值的时候编译器会自行对 block 进行 copy 操作, copy 到堆内存, 与一般的对象是相同的.
所以在 ARC 下 block 使用 copy 和 strong 是没有区别的.