以下代碼輸出結(jié)果如何甘萧?
NSString *name1 = [NSString stringWithFormat:@"haha"];
__weak NSString *name2 = name1;
NSLog(@"name1:%@", name1);
NSLog(@"name2:%@", name2);
name1 = nil;
NSLog(@"name1:%@", name1);
NSLog(@"name2:%@", name2);
NSString *a1 = [[NSString alloc] initWithFormat:@"haha"];
__weak NSString *a2 = a1;
NSLog(@"a1:%@", a1);
NSLog(@"a2:%@", a2);
a1 = nil;
NSLog(@"a1:%@", a1);
NSLog(@"a2:%@", a2);
NSString *b1 = @"haha";
__weak NSString *b2 = b1;
NSLog(@"b1:%@", b1);
NSLog(@"b2:%@", b2);
b1 = nil;
NSLog(@"b1:%@", b1);
NSLog(@"b2:%@", b2);
結(jié)果:
**2016-08-04 16:11:14.336 xxxxxxxx[677:238940] name1:haha**
**2016-08-04 16:11:14.337 xxxxxxxx[677:238940] name2:haha**
**2016-08-04 16:11:14.337 xxxxxxxx[677:238940] name1:(null)**
**2016-08-04 16:11:14.337 xxxxxxxx[677:238940] name2:haha**
****
****
**2016-08-04 16:11:14.338 xxxxxxxx[677:238940] a1:haha**
**2016-08-04 16:11:14.338 xxxxxxxx[677:238940] a2:haha**
**2016-08-04 16:11:14.338 xxxxxxxx[677:238940] a1:(null)**
**2016-08-04 16:11:14.339 xxxxxxxx[677:238940] a2:(null)**
****
****
**2016-08-04 16:11:14.339 xxxxxxxx[677:238940] b1:haha**
**2016-08-04 16:11:14.339 xxxxxxxx[677:238940] b2:haha**
**2016-08-04 16:11:14.340 xxxxxxxx[677:238940] b1:(null)**
**2016-08-04 16:11:14.340 xxxxxxxx[677:238940] b2:haha**
看到結(jié)果,有點匪夷所思,(name1, a1, b1)置空后杏愤,被__weak修飾的(name2, a2 b2)輸出怎么還會有東西?難道和NSString類型有關(guān)已脓,或者說和NSString的初始化方式有關(guān)珊楼?
如果是NSObject,輸出結(jié)果正常:
NSObject *obj1=[[NSObject alloc] init];
__strong NSObject *obj2 = obj1;
NSLog(@"%@,%@", obj1, obj2);
obj1 = nil;
NSLog(@"%@,%@", obj1, obj2);
NSObject *obj3=[[NSObject alloc] init];
__weak NSObject *obj4 = obj3;
NSLog(@"%@,%@", obj3, obj4);
obj3 = nil;
NSLog(@"%@,%@", obj3, obj4);
輸出結(jié)果正常度液,可看出strong與weak的區(qū)別:strong的對象會使retainCount+1厕宗,而weak不會。 所以第一個例子的retainCount為2堕担,obj1 = nil之后retainCount為1已慢,并不會對obj2造成影響;而第二個例子obj3 = nil后retainCount 為0了霹购,內(nèi)存也跟著釋放了佑惠,所以obj2也為nil。
**2016-08-05 09:32:49.918 xxxxxxxx[766:298464] <NSObject: 0x170b4780>,<NSObject: 0x170b4780>**
**2016-08-05 09:32:49.918 xxxxxxxx[766:298464] (null),<NSObject: 0x170b4780>**
****
**2016-08-05 09:32:49.919 xxxxxxxx[766:298464] <NSObject: 0x15f5d9d0>,<NSObject: 0x15f5d9d0>**
**2016-08-05 09:32:49.919 xxxxxxxx[766:298464] (null),(null)**
NSString也是一個NSObject齐疙,為什么它就不一樣膜楷?(同事的電腦輸出結(jié)果和我的還不一樣,如下圖贞奋,不知什么原因)
NSString *str1 = @"q"; // 與[NSString stringWithString:@"q"];等價
NSString *str2 = [NSString stringWithFormat:@"q"];
NSString *str3 = [[NSString alloc] initWithFormat:@"q"];
NSString *str4 = [[NSMutableString alloc] initWithString:@"q"];
NSLog(@"str1:%@", [str1 class]);
NSLog(@"str2:%@", [str2 class]);
NSLog(@"str3:%@", [str3 class]);
NSLog(@"str4:%@", [str4 class]);
str1 = @"afdjfdfjle”;
**2016-08-05 16:08:05.302 xxxxxxxxx[875:375798] str1:__NSCFConstantString**
**2016-08-05 16:08:05.303 xxxxxxxxx[875:375798] str2:__NSCFString**
**2016-08-05 16:08:05.303 xxxxxxxxx[875:375798] str3:__NSCFString**
**2016-08-05 16:08:05.303 xxxxxxxxx[875:375798] str4:__NSCFString**
可看出:
1.除str1類型為NSCFString(NSCFConstantString)外赌厅,其他的類型都為NSMutableString;
2.給str1賦值后打一個斷點,重新賦值后再打一個斷點忆矛,觀察str1的內(nèi)存地址發(fā)現(xiàn)已經(jīng)變了察蹲。有點意外吧请垛?按照 C 語言的經(jīng)驗,初始化一個字符串之后洽议,字符串的首地址就被確定下來宗收,不管之后如何修改字符串內(nèi)容,這個地址都不會改變亚兄。但此處第10行并不是對 str1 指向的內(nèi)存地址重新賦值混稽,因為賦值操作符左邊的 str1 是一個指針,也就是說此處修改的是內(nèi)存地址审胚。 所以第10行應(yīng)該這樣理解:將@"afdjfdfjle”當(dāng)做一個新的對象匈勋,將這段對象的內(nèi)存地址賦值給str。
NSString __weak *string = [[NSString alloc] initWithFormat:@"First Name: %@", @"A"];
NSLog(@"string:%@", string);
NSString __weak *string2 = @"B";
NSLog(@"string:%@", string2);
NSString __weak *string3 = [[NSString alloc] initWithString:@"C"];
NSLog(@"string:%@",string3);
**2016-08-05 09:55:50.923 Decoration[772:303138] string:(null)**
**2016-08-05 09:55:50.923 Decoration[772:303138] string:B**
**2016-08-05 09:55:50.923 Decoration[772:303138] string:C**
解釋:
1.沒有強引用的變量是會被立即釋放的膳叨,所以打印的string會是nil洽洁。
2.下面兩種情況(@""、initWithString)聲明的是常量字符串菲嘴,沒有retainCount(引用計數(shù))饿自,沒有強指針指向它,存在內(nèi)存靜態(tài)區(qū)龄坪,不會被銷毀昭雌,輸出自然會有結(jié)果。
回到最開始的問題:
分別在name1, a1, b1 置空前后打一個斷點觀察name2, a2, b2類型的變化健田,輸出結(jié)果應(yīng)該一目了然了吧烛卧。
**(lldb) p name2**
(__NSCFString *) $6 = 0x147c0210 @"haha"
**(lldb) p name2**
(__NSCFString *) $7 = 0x147c0210 @"haha"
**(lldb) p a2**
(__NSCFString *) $8 = 0x1581b480 @"haha"
**(lldb) p a2**
(NSString *) $9 = nil
**(lldb) p b2**
(__NSCFConstantString *) $10 = 0x00844fcc @"haha"
**(lldb) p b2**
(__NSCFConstantString *) $11 = 0x00844fcc @"haha"