以下代码输出结果如何?
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);
结果:
**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**
看到结果,有点匪夷所思,(name1, a1, b1)置空后,被__weak修饰的(name2, a2 b2)输出怎么还会有东西?难道和NSString类型有关,或者说和NSString的初始化方式有关?
如果是NSObject,输出结果正常:
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);
输出结果正常,可看出strong与weak的区别:strong的对象会使retainCount+1,而weak不会。 所以第一个例子的retainCount为2,obj1 = nil之后retainCount为1,并不会对obj2造成影响;而第二个例子obj3 = nil后retainCount 为0了,内存也跟着释放了,所以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,为什么它就不一样?(同事的电脑输出结果和我的还不一样,如下图,不知什么原因)
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的内存地址发现已经变了。有点意外吧?按照 C 语言的经验,初始化一个字符串之后,字符串的首地址就被确定下来,不管之后如何修改字符串内容,这个地址都不会改变。但此处第10行并不是对 str1 指向的内存地址重新赋值,因为赋值操作符左边的 str1 是一个指针,也就是说此处修改的是内存地址。 所以第10行应该这样理解:将@"afdjfdfjle”当做一个新的对象,将这段对象的内存地址赋值给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(引用计数),没有强指针指向它,存在内存静态区,不会被销毁,输出自然会有结果。
回到最开始的问题:
分别在name1, a1, b1 置空前后打一个断点观察name2, a2, b2类型的变化,输出结果应该一目了然了吧。
**(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"