我們在聲明一個NSString屬性時,對于其記憶體相關特性,通常有兩種選擇(基于ARC環境):strong與copy。那這兩者有什麼差別呢?什麼時候該用strong,什麼時候該用copy呢?
首先舉個例子:
這裡有一個person類,有一個使用cooy的NSString屬性.
毋庸置疑的是,字元串屬性使用copy,當外界修改了字元串,裡面不會改變.
在ViewController.m檔案中
注意: 此時的NSString屬性name是使用copy的.
- (void)viewDidLoad {
[super viewDidLoad];
// 不可變字元串
NSString *nameStr = @"zy";
Person *person = [[Person alloc] init];
person.name = nameStr;
NSLog(@"%p ---- %p",nameStr,person.name);
}
輸出結果:
因為NSString是不可變字元串,當使用copy的時候,不會生成一個新的對象,因為源對象是不可更改的對象,那麼拷貝出來的也是不可更改的對象,兩者互不影響.是以不會産生新的對象.
當把NSString的屬性改為strong,此時仍使用NSString不可變字元串.列印結果如下:
2017-08-31 18:23:36.487 NSSting_copy_strong[4747:199526] 0x103e44068 ---- 0x103e44068
是以,在不可變字元串的情況下,無論使用strong,還是copy.其位址指向的都是同一塊存儲空間.
注意: 當把.m檔案中的NSString不可變字元串改為可變字元串之後.
此時NSString的屬性使用的strong.
- (void)viewDidLoad {
[super viewDidLoad];
// 可變字元串
NSMutableString *nameStr = [NSMutableString stringWithFormat:@"zy"];
Person *person = [[Person alloc] init];
person.name = nameStr;
NSLog(@"%p ---- %p",nameStr,person.name);
}
輸出結果:
而把NSString的屬性改為copy後.
輸出結果:
此時copy屬性的字元串已經不再指向nameStr的記憶體位址了.而是深拷貝了一份記憶體位址,并讓 _name屬性指向這塊記憶體位址.
當源字元串是NSString的時候,無論使用strong,copy屬性的對象,都會指向源對象,此時copy隻是做了一次淺拷貝.
當源字元串是NSSMutableString的時候,copy屬性對源字元串做了一次深拷貝,建立了一個新的對象,并指向新對象的記憶體位址.
注意:
一般情況下我們在開發中使用的大多數都是NSString不可變字元串.在網絡中加載的資料大多也是不可變的.當使用不可變字元的時候,strong,copy都不會産生新的對象.這個時候建議使用strong;原因如下:
當NSString屬性使用copy的時候.
此時name的set方法是這樣的.
// copy情況下的屬性name的set方法
- (void)setName:(NSString *)name
{
_name = [name copy];
}
在set方法中,每次都會去判斷name是NSString的還是NSMutableString的.如果是NSString不可變字元串的時候,就不會去生成新的對象,如果是可變字元串,就會去生成新的對象.這樣會進行一次判斷操作.
當NSString屬性使用strong的時候
此時name的set方法是這樣的
// strong情況下的屬性name的set方法
- (void)setName:(NSString *)name
{
_name = name;
}
在set方法中不用去判斷,外界傳入的可變或不可變字元.這樣提高了性能.是以當外界傳入的字元串是NSString不可變字元串的時候,建議使用strong.
關于本章内容比較好的博文: http://www.cocoachina.com/ios/20150512/11805.html