我试图更好地理解强引用,但在一个特定的例子中,我将在下面列出。
假设我有一个全局变量gPrefs。它的类型是Preference Class,是我创建的一个自定义类。
我在它的接口中声明了如下内容…
@property (strong) NSURL *masterFolder;
这是指向NSURL对象的指针。我给了它(强)引用,这意味着它会一直存在,而不会释放它的内存。
现在让我们假设我在其他地方有一个实例函数,看起来像下面这样:
- (IBAction)masterDataSelectButtonAction:(id)sender
{
NSOpenPanel *openPanel = [NSOpenPanel openPanel];//creates an open panel.
[openPanel setCanChooseDirectories:YES];
[openPanel setCanChooseFiles:NO];
NSInteger panelResult = [openPanel runModal];
if(panelResult == NSFileHandlingPanelCancelButton){
NSLog(@"masterDataSelectButtonAction -> Cancel Button Pressed");
return;
}
if(panelResult == NSFileHandlingPanelOKButton){
NSLog(@"masterDataSelectButtonAction-> Ok Button Pressed");
NSURL *theUrl = [openPanel URL];
gPrefs.masterFolder = theUrl; //Setting (strong ref) point to local.
[_masterDataLabel setStringValue:[gPrefs.masterFolder absoluteString]];
}
}
如果用户按下面板的OK按钮,我将创建一个名为theUrl的本地指针实例变量。然后我将全局变量masterFolder指针设置为本地实例变量指针。
如果我理解正确的话,ARC应该在函数结束时释放对象,当它认为它不再被使用时。
因此url应该在函数结束时释放。
然而,如果我理解(强)引用,编译器可能足够聪明地意识到,由于我将全局首选项指针更改为不同的指针,它将使内存中的其他指针引用存活(或保留它)。
如果我没有声明我的masterFolder指针为(强),那么在函数结束后masterFolder指针会是nil吗?
我的实验表明,保持它(强)似乎保留了localInstance指针的值,尽管达到了本地实例函数的结束。
我的问题是为什么?即使masterFolder是一个强引用,如果我将它分配给localInstance指针,并且该指针在实例函数结束时被删除,为什么当我在其他任何地方的实例函数之外再次从它读取时,masterFolder的值不是NIL ?我对(强)引用的理解有点(弱)。没有双关语。
NSURL *theUrl = [openPanel URL];
theURL
在函数范围内(或在if
块内,但在本例中没有区别)。theURL
指向的对象在堆上。在函数结束时,当theURL
超出作用域时,堆上对象的引用计数将减少1(因为theURL
是对该对象的强引用)。如果此时引用计数变为0,则释放对象。在您的情况下,至少有一个其他强引用到对象(在您的全局单例中),因此对象保持存活。堆上的对象不是本地对象,因此内存不会超出作用域。
如果你的全局单例有一个弱引用,它将自动设置为nil
一旦对象的引用计数达到0,对象被释放。
那么坚强真的只是挽留。当你调用gPrefs.masterFolder = theUrl;
时,你正在做的是将指针masterFolder
设置为与theUrl
相同,并保留在masterFolder
上调用。因此,当创建theUrl
时,它的保留计数为1;当设置为masterFolder
的强属性时,theUrl
被调用了retain,使得它的retain计数增加到2。这就是为什么它不会消失,因为在实例方法完成后,url的初始自动释放发生了,theUrl
仍然有一个保留计数为1,因为它被设置为强属性。
现在,如果你将属性设置为weak,你会得到masterFolder
的行为是nil
和theUrl
被正确地销毁,一旦autorelease
发生,因为weak只是将masterFolder
设置为与theUrl
相同,但不调用retain。