为什么我会失去对此实例变量的访问权限?

时间:2011-09-01 14:49:28

标签: objective-c

zURL被声明为:

·H:

@interface PanelController : NSWindowController <NSWindowDelegate>
{
    NSURL *zURL;
}

@property (nonatomic, copy) NSURL *zURL;

.m:

@synthesize zURL;

在一项IBAction中,我有:

 - (IBAction)openBrowser:(id)sender {
    NSOpenPanel *zOpenPanel = [NSOpenPanel openPanel];
    [zOpenPanel setCanChooseFiles: TRUE];
    [zOpenPanel setCanChooseDirectories: TRUE];
    [zOpenPanel setAllowsMultipleSelection: TRUE];
    [zOpenPanel setLevel:CGShieldingWindowLevel()];
    NSInteger zIntResult = [zOpenPanel runModal];
    if (zIntResult == NSFileHandlingPanelCancelButton) {
        return;
    } 

    // zURL set here
    zURL = [NSURL alloc];
    zURL = [zOpenPanel URL];
    NSLog(@"url = %@", zURL); // works

    NSString *zStr = [zURL absoluteString];
    _fileField.stringValue = zStr;
    [_importButton setEnabled:TRUE];
    [self openPanel];
}

在下一次IBAction中:

NSLog(@"url = %@", zURL); // EXC_BAD_ACCESS error

3 个答案:

答案 0 :(得分:2)

您将自己的网址分配给zOpenPanel的网址属性,但并未表示您打算通过保留该网址来保留该引用。

zURL = [NSURL alloc]; // assign my variable to a new URL, allocating memory

您的第二行会使用对zOpenPanel的网址属性的引用来替换您的引用,从而泄露您刚才创建的网址。

稍后,zOpenPanel告诉操作系统完成了它的URL,并释放ram,从而使你的引用无效。

你可能想要做的事情:

zURL = [[zOpenPanel URL] retain];

这会分配您对zOpenPanel的网址属性的引用,并告诉操作系统您想要部分拥有它的生命周期。

当你完成zURL后,你需要释放它并放弃你的生命周期:

[zURL release];

编辑:

因为您将它声明为类的属性,所以应该使用属性表示法来调用相应的行为:

self.zURL = [zOpenPanel URL];

由于您已声明该属性具有复制语义,因此会复制该网址,您仍需要在dealloc中将其发布。

答案 1 :(得分:1)

在第一行中,您将分配NSURL,但不会调用初始化程序。在第二行中,您将从另一个位置分配zURL,丢失指向您在第一行中创建的对象的指针(这是内存泄漏)。

zURL存储在哪里?它是一个实例变量吗?如果是这样,您没有保留[zOpenPanel URL]返回的内容,因此无法保证在IBAction中调用时该对象未被释放。

答案 2 :(得分:0)

我怀疑你的zURL var在某个时候被释放了,正如乔治所指出的那样,如果你发布了如何宣告zURL会有所帮助。

此外,如果您要立即替换下一行的zURL值,则不需要执行[NSURL alloc]。