获取EXC_BAD_ACCESS,无法弄清楚如何解决它

时间:2011-09-04 22:24:35

标签: objective-c cocoa

目前我正在学习使用Cocoa开发Obj-C for Mac。我用一个检查器创建了一个简单的文件浏览器,以查看文件的图标和一些信息。到现在为止还挺好。现在我把它作为文档,所以我可以有多个打开的窗口。

告诉检查员应该检查哪个文件,我使用NSWindowDidBecomeMainNotification。适用于在窗口之间切换,但是当我关闭所有窗口然后打开一个新窗口时,它会给出EXC_BAD_ACCESS

这是处理通知的方法:

- (void)windowChanged: (NSNotification *)notification
{
    NSWindow *window = [notification object];
    BrowserWindow *doc = [[window windowController] document];

    if (currentDocument != doc) {

        [currentDocument.arrayController removeObserver: self
                                             forKeyPath: @"selectionIndex"];

        [icon setImage:nil];
        [size setStringValue:@"-"];
        [owner setStringValue:@"-"];
        [filename setStringValue:@"(none selected)"];

        [doc.arrayController addObserver: self
                              forKeyPath: @"selectionIndex"
                                 options: NSKeyValueObservingOptionNew 
                                 context: NULL];
        currentDocument = doc;
    }
}

removeObserver:forkeyPath:上调用currentDocument.arrayController时会发生错误。它有点意义,它试图移除观察者不再存在的东西,因为窗口关闭。但是如何解决呢?我想不出别的什么......

有人能指出我正确的方向吗?

我很感激帮助! :)

-

它变得越来越奇怪了。刚刚检查了可以从我所拥有的书的网站下载的例子,他们使用相同的方法,但它工作得很好。找不到任何差异,这让我发疯了。

-

解决!稍后会详细介绍。

2 个答案:

答案 0 :(得分:2)

Daniel可能是对的:您可能不会保留currentDocument。将currentDocument设为属性:

@property (retain) BrowserWindow *currentDocument;

并在实现部分中进行综合:

@synthesize currentDocument;

并将您的代码更改为:

- (void) windowChanged: (NSNotification *) notification
{
    NSWindow *window = [notification object];
    BrowserWindow *doc = [[window windowController] document];

    if (self.currentDocument != doc) 
    {
        [self.currentDocument.arrayController removeObserver: self
                                                  forKeyPath: @"selectionIndex"];

        [icon setImage: nil];
        [size setStringValue: @"-"];
        [owner setStringValue: @"-"];
        [filename setStringValue: @"(none selected)"];

        [doc.arrayController addObserver: self
                              forKeyPath: @"selectionIndex"
                                 options: NSKeyValueObservingOptionNew 
                                 context: NULL];
        self.currentDocument = doc;
    }
}

您可能希望对图标尺寸所有者文件名执行相同的操作。

并注意到这个信息的警告:你可能不会将自己注册为观察者开始。

答案 1 :(得分:1)

  

告诉检查员应该检查哪个文件,我使用NSWindowDidBecomeMainNotification。适用于在窗口之间切换,但是当我关闭所有窗口然后打开一个新窗口时,它会给出EXC_BAD_ACCESS

这是问题的一部分。当最后一个窗口关闭时,没有窗口将成为主窗口。因此,您还需要处理窗口重新启动 main的情况,就像它关闭时(以及当另一个窗口变为主窗口时)。

您的检查员可能应该在延迟之后保留文档并切换文档,使用计时器(每当另一个确实变为/辞职主要通知时,您的发布日期推迟)或延迟执行(您取消并重新执行)每次)。当计时器/执行触发时,找出哪个文档(如果有的话)是活动文档,并相应地更新检查器。

另请注意,即使打开文档,您也可以没有活动文档(没有文档窗口是主窗口)。 “关于”面板和“首选项”面板是实现(和测试)此功能的两种好方法。