既然上篇提到了copy相關(guān)的知識點,那么趁熱打鐵介紹一下為什么字符串的屬性,要用copy修飾。
介紹之前,先回憶一下屬性修飾符都有哪些:
MRC:
assign:基本數(shù)據(jù)類型(當(dāng)出現(xiàn)循環(huán)引用時,也要用assign)
retain:除Block和NSString外的其他對象
copy:一般用于NSString和Block
ARC:
strong:默認
weak:多用于ui和解決循環(huán)引用
copy:用于NSString和Block
assign:非OC對象
既然NSString屬于OC對象,那么我們先不使用Copy修飾,在ARC模式下,聲明的屬性默認是strong修飾,接下來就演示strong修飾NSString的后果
先定義一個AMPerson類,如下:
@interface AMPerson : NSObject
@property (strong,nonatomic)NSString *name;
@end
在控制器中的viewDidLoad方法中編輯如下代碼:
AMPerson *p = [[AMPerson alloc] init];
NSMutableString *str = [NSMutableString string];
[str appendString:@"anmav"];
p.name = str;
[str appendString:@"yc"];
NSLog(@"%@",p.name);
打印結(jié)果為:anmavyc
結(jié)果分析: 如果使用strong修復(fù)NSString類型屬性,p.name 指向可變字符串對象的地址,當(dāng)可變字符串內(nèi)容發(fā)生變化時,p.name相對應(yīng)的也發(fā)生變化。
使用copy修飾后,將可變字符串重新拷貝一份,重新開辟內(nèi)存空間,修改mutableString的值,不會對p.name造成影響。
剛剛的演示,我使用了NSMutableString(可變字符串),對mutableString執(zhí)行copy操作,屬于深拷貝,所以開辟的新內(nèi)存空間,如果使用的是NSString(不可變內(nèi)存),對NSString進行copy屬于淺拷貝,不會開辟新的內(nèi)存空間,是不是就不會出現(xiàn)這個問題了呢?
AMPerson *p = [[AMPerson alloc] init];
NSString *str = [NSString string];
str = @"anmav";
p.name = str;
str = @"yc";
NSLog(@"%@",p.name);
打印結(jié)果為:anmav
將之前的可變字符串變?yōu)椴豢勺冏址?因為NSString不支持append添加操作,我這里的兩次str賦值操作,其實是讓str重新指向了一片內(nèi)存空間,并不是修改了str原本內(nèi)存中的值
(OC中對象即指針,實際上存儲的是內(nèi)存地址,p.name = str; 實際是將str存儲的@"xiaoming"這塊地址給了p.name,p.name還指向著@"xiaoming")
所以改變str的指向后,p.name的指向并沒有改變,輸出沒有受到影響