目前我正在学习使用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
时会发生错误。它有点意义,它试图移除观察者不再存在的东西,因为窗口关闭。但是如何解决呢?我想不出别的什么......
有人能指出我正确的方向吗?
我很感激帮助! :)
-
它变得越来越奇怪了。刚刚检查了可以从我所拥有的书的网站下载的例子,他们使用相同的方法,但它工作得很好。找不到任何差异,这让我发疯了。
-
解决!稍后会详细介绍。
答案 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的情况,就像它关闭时(以及当另一个窗口变为主窗口时)。
您的检查员可能应该在延迟之后保留文档并切换文档,使用计时器(每当另一个确实变为/辞职主要通知时,您的发布日期推迟)或延迟执行(您取消并重新执行)每次)。当计时器/执行触发时,找出哪个文档(如果有的话)是活动文档,并相应地更新检查器。
另请注意,即使打开文档,您也可以没有活动文档(没有文档窗口是主窗口)。 “关于”面板和“首选项”面板是实现(和测试)此功能的两种好方法。