为什么弱的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 ,但我不确定。