之前有過一篇文章關于iOS 屬性的 iOS指示符 assign摹菠、copy套啤、retain、strong改化、weak,之后看了一遍有總結了一下:
NSString 選 Strong 還是copy枉昏?
1陈肛、現(xiàn)分別創(chuàng)建NSString 的strong 和 copy 兩個屬性
@property(nonatomic, strong) NSString *age1;
@property(nonatomic, copy) NSString *age2;
2、創(chuàng)建一個NSString 常量凶掰,賦值給上面的age1和age2兩個屬性燥爷。
NSString *age = @"11";
NSLog(@"age: %@ - %p", age, age);
self.age1 = age;
self.age2 = age;
NSLog(@"age1: %@ - %p", self.age1, self.age1);
NSLog(@"age2: %@ - %p", self.age2, self.age2);
NSString *ageOther = [age stringByAppendingString:@"20"];
NSLog(@"age: %@ - %p", age, age);
NSLog(@"ageother: %@ - %p", ageOther, ageOther);
NSLog(@"age1: %@ - %p", self.age1, self.age1);
NSLog(@"age2: %@ - %p", self.age2, self.age2);
3、結果:
age: 11 - 0x108f28078
age1: 11 - 0x108f28078
age2: 11 - 0x108f28078
age: 11 - 0x108f28078
ageother: 1120 - 0x600000255000
age1: 11 - 0x108f28078
age2: 11 - 0x108f28078
分析:
我們可以發(fā)現(xiàn)懦窘,給age1和age2 賦值一個不可變的字符串的時候前翎,都進行了淺拷貝,只拷貝了指針地址畅涂,使age港华、age1、age2都指向同一個地址午衰,在對age進行增加字符串時立宜,因為age是不可變字符串,所以age沒有變化臊岸,于是age1橙数、age2都沒有變化。
總結:聲明String和copy屬性的String被不可變String賦值時帅戒,沒有變化灯帮,都是淺拷貝,都不會發(fā)生變化逻住。
1钟哥、現(xiàn)分別創(chuàng)建NSString 的strong 和 copy 兩個屬性
@property(nonatomic, strong) NSString *str1;
@property(nonatomic, copy) NSString *str2;
2、創(chuàng)建一個NSMutableString 可變字符串瞎访,賦值給上面的str1和str2兩個屬性腻贰。
NSMutableString *name = [[NSMutableString alloc] initWithString:@"Alex"];
NSLog(@"name : %@ - %p", name, name);
self.str1 = name;
self.str2 = name;
NSLog(@"str1 %@ - %p", self.str1, self.str1);
NSLog(@"str2 %@ - %p", self.str2, self.str2);
[name appendString:@"Le"];
NSLog(@"str1 %@ - %p", self.str1, self.str1);
NSLog(@"str2 %@ - %p", self.str2, self.str2);
3、結果:
name : Alex - 0x604000255cc0
str1 : Alex - 0x604000255cc0
str2 : Alex - 0xa00000078656c414
str1 : AlexLe - 0x604000255cc0
str2 : Alex - 0xa00000078656c414
分析:
我們可以看出在用可變字符串給屬性變量賦值時扒秸,strong的str1 對name進行淺拷貝播演,只拷貝了地址冀瓦,所以str1和name指向同一個地址,而copy 的 str2 對name 進行了深拷貝写烤,str2將name復制到一個新空間內(nèi)咕幻。
當我們對name增添時,此時我們可以看到和name指向相同的str1的內(nèi)容改變了顶霞,而新開辟空間的str2卻還保持原來的值。
總結:
聲明String和copy屬性的String被可變的NSMutableString name賦值時锣吼,strong類型的會隨可變字符串的變化而變化选浑,但是copy類型的卻不會隨可變字符串的變化而變化。所以當屬性被不可變的字符串賦值時玄叠,strong和copy沒有區(qū)別古徒;當屬性被可變字符串賦值時,copy不會被修改读恃,而strong會被修改隧膘。綜上所述,copy更簡單寺惫、安全疹吃。
NSArray 和 NSMutableArray 是 copy 還是 strong?
1西雀、NSMutableArray 不能被copy修飾萨驶,因為以后對數(shù)組的增刪改操作在copy之后數(shù)組都會變成不可變數(shù)組,對其進行增刪改都將crash艇肴。
@property (copy) NSMutableArray * a;
NSMutableArray* b = [NSMutableArray array];
a = b;
等同于
@property (strong) NSMutableArray * a;
NSMutableArray* b = [NSMutableArray array];
a = [b copy];
a在被copy之后就變成了不可變數(shù)組NSArray了腔呜。
2、NSMutableArray 被strong修飾再悼,在賦值的時候就如上面說的那樣會指向同一個地址核畴,被定義的屬性也不會改變。
@property(nonatomic, strong) NSMutableArray *arrayA;
@property(nonatomic, copy) NSMutableArray *arrayB;
NSMutableArray *arrayC = [NSMutableArray array];
NSLog(@"arrayC.class: %@ - %p", arrayC.class, arrayC);
self.arrayA = arrayC;
self.arrayB = arrayC;
NSLog(@"arrayA.class: %@ - %p", _arrayA.class, _arrayA);
NSLog(@"arrayB.class: %@ - %p", _arrayB.class, _arrayB);
[self.arrayA removeAllObjects];
[self.arrayB removeAllObjects];
結果:
arrayC.class: __NSArrayM - 0x604000251220
arrayA.class: __NSArrayM - 0x604000251220
arrayB.class: __NSArray0 - 0x6000000021a0
-[__NSArray0 removeAllObjects]: unrecognized selector sent to instance 0x6000000021a0
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArray0 removeAllObjects]: unrecognized selector sent to instance 0x6000000021a0'
分析:我們可以看到arrayA 和 arrayC的指向同一個地址冲九,且類型都是mutable的谤草,arrayB的類型發(fā)生了改變變成不可變的類型。所以娘侍,NSMutableArray被copy修飾之后就變成不可變的咖刃,在對其操作時容易crash。
而NSArray被copy或者strong修飾的時候和NSString相同憾筏。
1嚎杨、當arrayA被strong修飾,且被可變數(shù)組賦值氧腰,可變數(shù)組arrayMB改變枫浙,被strong修飾屬性arrayA也做同樣修改刨肃,arrayA和arrayMB指向的地址相同;
2箩帚、當array被copy修飾真友,且被可變數(shù)組賦值,可變數(shù)組arrayMB改變紧帕,被copy修飾的屬性arrayB沒有被修改盔然,因為arrayB深拷貝arrayMB,arrayB和arrayMB在兩個內(nèi)存塊中是嗜。
3愈案、不管array被strong、copy修飾鹅搪,只要被不可變數(shù)組賦值站绪,此時都指向同一個內(nèi)存地址。