强引用(目标-C)



我试图更好地理解强引用,但在一个特定的例子中,我将在下面列出。

假设我有一个全局变量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的行为是niltheUrl被正确地销毁,一旦autorelease发生,因为weak只是将masterFolder设置为与theUrl相同,但不调用retain。

相关内容

  • 没有找到相关文章

最新更新