为什么弱的NSString属性不能在iOS中发布?
我写了下面的示例代码来看看ARC如何工作
@property (nonatomic, weak) NSString *myString; @property (nonatomic, weak) NSObject *myObj; @end @implementation ViewController @synthesize myString = _myString; @synthesize myObj = _myObj; - (void) viewDidAppear:(BOOL)animated { NSLog(@"Appearing Obj: !%@!",self.myObj); NSLog(@"Appearing String: !%@!",self.myString); } - (void)viewDidLoad { self.myObj = [[NSObject alloc] init]; self.myString = [[NSString alloc] init]; NSLog(@"Loading Obj %@",self.myObj); NSLog(@"Loading String: !%@!",self.myString); }
然而令人惊讶的是我得到了这些结果
2012-06-19 15:08:22.516 TESTER[4041:f803] Loading Obj (null) 2012-06-19 15:08:22.517 TESTER[4041:f803] Loading String: !! 2012-06-19 15:08:22.533 TESTER[4041:f803] Appearing Obj: !(null)! 2012-06-19 15:08:22.535 TESTER[4041:f803] Appearing String: !!
正如你所看到的,Obj得到正确的释放,但我的string(这也是一个弱财产)不打印出null …为什么不呢?
NSString
使用各种各样的内部欺骗来重用对象,并避免不必要的分配和复制。 它可以这样做,因为NSString
实例是不可变的。 在这种情况下,可能有一个共享实例来表示由[[NSString alloc] init]
返回的空string,而这个共享实例将作为一个单独的实例保留在其他地方。
[[NSString alloc] init]
总是返回相同的值。 你可以自己检查一下。
NSString *string1 = [[NSString alloc] init]; NSString *string2 = [[NSString alloc] init]; NSString *string3 = [[NSString alloc] init]; NSLog(@"string1 = %p, string2 = %p, string3 = %p", string1, string2, string3)
该代码返回三个相同的地址。 在我的情况下,输出是:
string1 = 0x3e8dd74c, string2 = 0x3e8dd74c, string3 = 0x3e8dd74c
这意味着[[NSString alloc] init]
返回Singleton 。 单身通常不能被释放。
使用其他方法(如initWithFormat:
string会生成通常可以释放的通常的“非单例”对象,但有一些例外情况。
进一步的:查看源代码(汇编):
-[NSPlaceholderString init]: 00040ea4 f64b009c movw r0, 0xb89c 00040ea8 f2c00016 movt r0, 0x16 00040eac 4478 add r0, pc 00040eae 4770 bx lr
这将是这样的(在ObjectiveC中)
-(id)init { return SOME_CONSTANT_VALUE; }
这可能是kCFEmptyString
,但我不确定。