strong修饰
- 要给属性NSString赋一个不可变的值时,用strong
缘由:
如果使用copy来修饰属性,在进行赋值的时候,会先做一个类型判断,如果赋的值是一个不可变的字符串,则走strong的策略,进行的是浅拷贝;如果是可变的字符串,则进行深拷贝创建一个新的对象。所以如果我们确定是给属性赋值一个不可变的值,就不用copy再多去判断一遍类型,因为如果是很多的NSString属性需要赋值,会极大的增加系统开销。所以用strong在此情况下可以提升性能。
代码示例:
声明两个变量
@property (nonatomic, strong) NSString *strongString;
@property (nonatomic, copy) NSString *copyedString;
不可变字符串赋值
- (void)viewDidLoad {
[super viewDidLoad];
NSString *string = [NSString stringWithFormat:@"lalala"];
self.strongString = string;
self.copyedString = string;
NSLog(@"origin string: %p, %p", string, &string);
NSLog(@"strong string: %p, %p", _strongString, &_strongString);
NSLog(@"copyed string: %p, %p", _copyedString, & _copyedString);
}
结果
2019-08-30 14:22:00.546434+0800 test[1150:566116] origin string: 0x9c1dc136cdff7947, 0x7ffee0870a88
2019-08-30 14:22:01.756447+0800 test[1150:566116] strong string: 0x9c1dc136cdff7947, 0x7fd4eb70a3e0
2019-08-30 14:22:02.937356+0800 test[1150:566116] copyed string: 0x9c1dc136cdff7947, 0x7fd4eb70a3e8
换成
NSString *string = [NSString stringWithFormat:@"lalala"];
_strongString = string;
_copyedString = string;
NSLog(@"origin string: %p, %p", string, &string);
NSLog(@"strong string: %p, %p", _strongString, &_strongString);
NSLog(@"copyed string: %p, %p", _copyedString, & _copyedString);
结果一样
2019-08-30 14:24:09.758115+0800 test[2070:572063] origin string: 0xaae3606a066107fb, 0x7ffee36c9a88
2019-08-30 14:24:09.758307+0800 test[2070:572063] strong string: 0xaae3606a066107fb, 0x7fed62602c60
2019-08-30 14:24:09.758403+0800 test[2070:572063] copyed string: 0xaae3606a066107fb, 0x7fed62602c68
结论
- 对于不可变的字符串修饰不管是strong还是copy属性的对象,其指向的地址都是同一个,即为string指向的地址。
copy修饰
前提我们用self.name
- 修饰可变的字符串,当它发生变化时,用strong修饰的属性会发生变化,而copy修饰是深拷贝,不会发生变化。
- 当可变字符串赋值我们希望,值不变用strong 都是指向同一个地址
- 当可变字符串赋值我们希望,值改变,创建一个新的对象,用copy(调用用self.name)
- 但是大多数情况下我们不确定是可变的还是不可变的使用copy来修饰,这样保证了安全性
代码示例:
NSMutableString *mutbleString = [NSMutableString stringWithFormat:@"hahaha"];
self.strongString = mutbleString;
self.copyedString = mutbleString;
[mutbleString appendString:@" wawawa"];
结果
2019-08-30 15:09:26.257451+0800 test[15589:652086] origin string: 0x6000028e0c00, 0x7ffeebc10a88
2019-08-30 15:09:26.257633+0800 test[15589:652086] strong string: 0x6000028e0c00, 0x7ff4e8c09320
2019-08-30 15:09:26.257731+0800 test[15589:652086] copyed string: 0xcebcae1ddfc2b804, 0x7ff4e8c09328
结论:
当我们赋值时用self 这时候strong 修饰的字符串和可变的字符串指向同一个对象,而copy 修饰的时候发生了变化,是深拷贝创建了一个新的对象,所以,当可变字符串发生改变时,strong 修饰的也会发生改变,但是copy 修饰的不会发生改变,。
代码示例
NSMutableString *mutbleString = [NSMutableString stringWithFormat:@"hahaha"];
_strongString = mutbleString;
_copyedString = mutbleString;
[mutbleString appendString:@" wawawa"];
NSLog(@"origin string: %p, %p", mutbleString, &mutbleString);
NSLog(@"strong string: %p, %p", _strongString, &_strongString);
NSLog(@"copyed string: %p, %p", _copyedString, & _copyedString);
结论
同样用,strong 和copy 来修饰,但是用self.name 和_.name
结论是不一样的,
用可变的字符串赋值用_name 时这时候指向同一个对象
缘由:
- self.name 是对属性的访问是调用的name属性的getter/setter方法
- _name 是对局部变量的访问并不会调用getter/setter方法
总结:self方法实际上是用了get和set方法间接调用,下划线方法是直接对变量操作。