为什么强壮的人走后,我的弱言辞就没有被清除?

我有点固执,但是我想很好地理解弱和强的引用,所以我再次问你。

考虑这个:

__weak NSString* mySecondPointer = myText; NSLog(@"myText: %@", myText); 

结果是myText: (null) ,它非常明显 – 弱赋值在赋值后被设置为null,因为没有强引用指向的对象。

但在这种情况下:

 __strong NSString* strongPtr = [[NSString alloc] initWithFormat:@"mYTeSTteXt %d"]; // weak pointer points to the same object as strongPtr __weak NSString* weakPtr = strongPtr; if(strongPtr == weakPtr) NSLog(@"They are pointing to the same obj"); NSLog(@"StrongPtr: %@", strongPtr); NSLog(@"weakPtr: %@", weakPtr); NSLog(@"Setting myText to different obj or nil"); // after line below, there is no strong referecene to the created object: strongPtr = [[NSString alloc] initWithString:@"abc"]; // or myText=nil; if(strongPtr == weakPtr) NSLog(@"Are the same"); else NSLog(@"Are NOT the same"); NSLog(@"StrongPtr: %@", strongPtr); // Why weak pointer does not point to nul NSLog(@"weakPtr: %@", weakPtr); 

输出:

 2013-03-07 09:20:24.141 XMLTest[20048:207] They are pointing to the same obj 2013-03-07 09:20:24.142 XMLTest[20048:207] StrongPtr: mYTeSTteXt 3 2013-03-07 09:20:24.142 XMLTest[20048:207] weakPtr: mYTeSTteXt 3 2013-03-07 09:20:24.143 XMLTest[20048:207] Setting myText to different obj or nil 2013-03-07 09:20:24.143 XMLTest[20048:207] Are NOT the same 2013-03-07 09:20:24.144 XMLTest[20048:207] StrongPtr: abc 2013-03-07 09:20:24.144 XMLTest[20048:207] weakPtr: mYTeSTteXt 3 // <== ?? 

我的问题:

为什么在strongPtr = [[NSString alloc] initWithString:@"abc"]; 弱指针值不会变为零(为什么在开始时创build的对象仍然存在于内存中,尽pipe它没有强引用?或者它可能有?)


我已经尝试过这样一个:(但是,这是不好的,我想添加一个评论)。 我已经包含了我在@autorealesepool中创build一个strongPtr的代码。 我不知道这是否是正确的解决scheme,但它的工作…

  __strong NSString* strongPtr; __weak NSString* weakPtr; @autoreleasepool { strongPtr = [[NSString alloc] initWithFormat:@"mYTeSTteXt %d", 3]; // weak pointer point to object create above (there is still strong ref to this obj) weakPtr = strongPtr; if(strongPtr == weakPtr) NSLog(@"They are pointing to the same obj"); NSLog(@"StrongPtr: %@", strongPtr); NSLog(@"weakPtr: %@", weakPtr); NSLog(@"Setting myText to different obj or nil"); // after line below, there is no strong referecene to the created object: strongPtr = [[NSString alloc] initWithString:@"abc"]; } if(strongPtr == weakPtr) NSLog(@"Are the same"); else NSLog(@"Are NOT the same"); NSLog(@"StrongPtr: %@", strongPtr); // Why weak pointer does not point to nul NSLog(@"weakPtr: %@", weakPtr); 

输出:

 2013-03-07 09:58:14.601 XMLTest[20237:207] They are pointing to the same obj 2013-03-07 09:58:14.605 XMLTest[20237:207] StrongPtr: mYTeSTteXt 3 2013-03-07 09:58:14.605 XMLTest[20237:207] weakPtr: mYTeSTteXt 3 2013-03-07 09:58:14.606 XMLTest[20237:207] Setting myText to different obj or nil 2013-03-07 09:58:14.607 XMLTest[20237:207] Are NOT the same 2013-03-07 09:58:14.607 XMLTest[20237:207] StrongPtr: abc 2013-03-07 09:58:14.608 XMLTest[20237:207] weakPtr: (null) 

从汇编代码可以看出,访问weakPtr生成一个objc_loadWeak调用。

根据Clang文档 , objc_loadWeak保留并自动释放对象,相当于

 id objc_loadWeak(id *object) { return objc_autorelease(objc_loadWeakRetained(object)); } 

这(希望)解释了为什么这两个

 if(strongPtr == weakPtr) ... 

 NSLog(@"weakPtr: %@", weakPtr); 

创build额外的autoreleased引用。

这不是一个特殊的NSString问题,我可以重现与自定义(普通)类相同的行为。

首先,不要在NSString上试验弱引用或者其他内存pipe理行为,这个类有太多的魔法。 不是那些弱引用不能用于NSString ,只是行为比你期望的稍微复杂一些,容易导致错误的结论。 看到这些以前的问题:

  • 弱的attritube不按预期工作
  • 为什么弱的NSString属性不能在iOS中发布?
  • NSString保留计数

当你用自动释放池包装你的代码示例,然后logging弱string指针,它确实没有。 甚至可能会出现类似于NSString类以外的行为的情况 – 你不能保证弱引用在你丢失对象的最后一个强引用的时刻被清除。 或者,也许你是这样的,但是很难说这个例子中暗示了什么时候由于自动释放池的存在而最后一个强引用消失了(马丁的回答很好地解释了这个问题)。

当你这样做

strongPtr = [[NSString alloc] initWithString:@“abc”]

你的strongPtr指向新分配的对象,并且由于它指向的上一个对象也没有被释放,所以弱指针仍然指向一个有效的地址。

顺便说一句。 你可以打印一个对象的内存地址

NSLog(@“%@”,[NSString stringWithFormat:@“%p”,theObject])

不确定OP的问题和/或接受的答案是否仍然有效,至less不是我在iOS9 / Xcode7中看到的结果。

这是一个(稍微清理)OP的代码版本…

 #import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { NSString* __strong strongPtr = [[NSString alloc] initWithFormat:@"Life, Universe, Everything: %d", 42]; NSString* __weak weakPtr = strongPtr; NSLog(strongPtr == weakPtr ? @"Same" : @"Different"); NSLog(@" StrongPtr: %@", strongPtr); NSLog(@" weakPtr: %@", weakPtr); NSLog(@"Changing strongPtr to something else..."); // After this is set, there is no strong reference to the created object strongPtr = [[NSString alloc] initWithFormat:@"Drink: %@", @"Pan-galactic Gargle Blaster!"]; NSLog(strongPtr == weakPtr ? @"Same" : @"Different"); NSLog(@" StrongPtr: %@", strongPtr); NSLog(@" weakPtr: %@", weakPtr); } return 0; } 

这里是(截断的)输出…

 Same StrongPtr: Life, Universe, Everything: 42 weakPtr: Life, Universe, Everything: 42 Changing strongPtr to something else... Different StrongPtr: Drink: Pan-galactic Gargle Blaster! weakPtr: (null) Program ended with exit code: 0 

这里访问条件中的弱引用(按照接受的答案的解释)不会像输出中的(null)那样保持自动释放的引用。

…或者我是否意外地把OP的问题改变到隐藏他所看到的地步? 或者也许是因为现在ARC默认打开了?