我有点顽固,但我想要了解弱弱和强烈的参考资料,这就是我再次问你的原因。
考虑一下:
__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"];
弱指针值未更改为nil之后(为什么在开头创建的对象仍然存在于内存中,尽管它没有任何强引用? - 或者它可能有?)
我试过那个:(但是我觉得添加评论不好)。我已经包含了我在@autorealesepool中创建strongPtr的代码。我不确定它是否是正确的解决方案,但它有效...
__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)
答案 0 :(得分:17)
从汇编代码可以看出,访问weakPtr
会产生objc_loadWeak
来电。
根据Clang documentation,objc_loadWeak
保留并自动释放对象并等同于
id objc_loadWeak(id *object) {
return objc_autorelease(objc_loadWeakRetained(object));
}
这(希望)解释了为什么两者
if(strongPtr == weakPtr) ...
和
NSLog(@"weakPtr: %@", weakPtr);
创建其他自动释放的参考文献。
这不是一个特殊的NSString
问题,我可以使用自定义(普通)类重现相同的行为。
答案 1 :(得分:3)
首先,不要在NSString
上试验弱引用或其他内存管理行为,这个类中有太多魔法。并不是弱引用不适用于NSString
,只是行为比你想象的稍微复杂,并且很容易导致不正确的结论。请参阅以前的这些问题:
当您使用自动释放池包装代码示例并在之后记录弱字符串指针时,它确实是nil
。甚至可能会出现与NSString
以外的类相似的行为 - 您无法保证在丢失对对象的最后一个强引用的精确时刻将清除弱引用。或者也许你是,但是很难说出最后一个强引用是否会因为自动释放池的消失而消失,正如这个例子暗示的那样(并且很好地解释了Martin的答案)。
答案 2 :(得分:1)
当你做
时strongPtr = [[NSString alloc] initWithString:@“abc”]
你strongPtr指向新分配的对象,并且由于它指向的前一个对象也没有被释放,弱指针仍然指向一个有效的地址。
顺便说一句。您可以使用
打印对象的内存地址NSLog(@“%@”,[NSString stringWithFormat:@“%p”,theObject])
答案 3 :(得分:1)
不确定OP的问题和/或此处接受的答案是否仍然有效,至少不是我在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默认开启了?