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
答案 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]。