专题:XX1iOS收藏ios

NSString 为什么用 copy ? Block 为什么用

2017-04-10  本文已影响308人  幸运者_Lucky

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 是没有区别的.

上一篇下一篇

猜你喜欢

热点阅读