【问题标题】:In NSWindowController subclass, [self document] returns null在 NSWindowController 子类中,[self document] 返回 null
【发布时间】:2010-09-07 14:53:24
【问题描述】:

我正在使用NSDocument 的自定义子类和NSWindowController 的自定义子类。问题是我无法从我的自定义窗口控制器中引用我的自定义文档。

在 IB 中,在 TKDocument NIB 中,我将文件所有者设置为 TKWindowController

在我的TKDocument 子类中,我有:

- (void) makeWindowControllers {
     TKWindowController *controller = [[TKWindowController alloc] init];
     [self addWindowController:controller];
}

然后在我的TKWindowController 子类中我覆盖setDocument 以确保它被调用:

- (void) setDocument(NSDocument *) document {
     NSLog(@"setDocument:%@", document);
     [super setDocument:document];
}

然后(再次在TKWindowController)我的操作引用了文档本身:

- (IBAction) plotClicked:(id) sender {
     TKDocument *doc = [self document];
     NSLog(@"plotClicked %@", doc);
}

setDocument 中的 NSLog 输出我的 [TKDocument description] 覆盖返回的字符串,正如我所期望的那样;我只是把它放在那里看看它是否被调用。但是,plotClicked 中的 doc 为空。

我可能做错了什么?

编辑:我认为问题与 NIB 有关。我的文档有自己的 NIB,文件的所有者设置为上面提到的自定义控制器。 plotClicked 操作从 MainMenu.xib 中的菜单项触发。我相信它正在访问与当前活动文档无关的控制器的新实例。

那么,如何将两者联系起来呢?我的问题是:如何从 MainMenu.xib 获取当前活动文档(或其窗口控制器)的句柄?

谢谢

【问题讨论】:

    标签: cocoa


    【解决方案1】:

    我的文档有自己的 NIB,文件的所有者设置为上面提到的自定义控制器。

    文档 nib 的文件所有者应该是文档。考虑一下嫌疑人 #1。

    plotClicked 动作从 MainMenu.xib 中的菜单项触发。我相信它正在访问与当前活动文档无关的控制器的新实例。

    您是否在主菜单笔尖中放置了一个窗口控制器?如果不是,那么这不是问题,因为您必须将您的 plotClicked: 菜单项连接到 First Responder,并且窗口控制器及其文档将在响应者链中。

    如果您这样做了,那么解决方案就是:从 MainMenu nib 中删除窗口控制器,并将您的菜单项连接到 First Responder,这样操作消息就会沿着响应者链向下传递,从而使其能够访问文档或窗口控制器。

    如何获得...的句柄?

    Mac 上唯一的手柄来自 Carbon;这些句柄在 Cocoa 中不存在。

    【讨论】:

    • 彼得,谢谢。我确实有一个窗口控制器,后来我把它删除了。我现在已将菜单项连接到 First Responder,它现在可以工作了。我不确定 为什么 它起作用:我知道事件正在沿着响应者链向下传播,但是我的窗口控制器上的动作 plotClicked 在文档笔尖中是未连接的。我需要阅读更多相关信息。
    • 您说文件的所有者应该是文档。使用自定义窗口控制器时仍然是这种情况吗?如果是这样,我如何访问 NIB 中的控制器?我认为在文档 NIB 中实例化自定义窗口控制器是不正确的。感谢您之前对一个相当模糊的问题的明确回答。
    • 您不会在任何 nib 中实例化窗口控制器,因为它的工作是加载 nib。为什么要从 nib 中的对象访问控制器而不是文档?
    • 至于操作:您不需要将窗口控制器(或文档)的操作直接连接到任何东西。正如我所说,文档及其窗口控制器将在适当的时间位于响应者链中,因此只要您的菜单项和控件针对 First Responder,它们就会在适当的时候点击文档/WC,并且不在时不。当没有活跃的响应者可以处理它们时,菜单项也会禁用它们自己。相关文档:developer.apple.com/mac/library/documentation/Cocoa/Conceptual/…
    • @BrunoVDK 嗯。我认为文档是错误的; Xcode 中基于文档的应用项目模板已设置为文档类,并且 nib 必须反映现实;实际上文件的所有者是什么对象不是由笔尖确定的。请提交错误:bugreport.apple.com
    【解决方案2】:

    init 不是 NSWindowController 的指定初始化器。您想要其中之一:– initWithWindow:– initWithWindowNibName:– initWithWindowNibName:owner:– initWithWindowNibPath:owner:

    另外,来自the docs

    在你的类的初始化方法中, 一定要调用 super 任何一个 initWithWindowNibName:... 初始化程序或 initWithWindow: 初始化器。取决于哪一个 窗口对象是否源自 在 nib 文件中或以编程方式 已创建。

    【讨论】:

    • 谢谢,虽然我不认为是这样,因为我的 init 方法包括对 [super initWithWindowNibName:@"TKDocument"] 的调用。如果更好的做法,我会直接从 Document 调用 initWithWindowNibName 并在 Controller 中覆盖它以执行我的其他初始化。
    • TimG:如果您的自定义 init 调用了 NSWindowController 的初始化程序之一,则可以调用您的自定义 init
    猜你喜欢
    • 2015-09-17
    • 1970-01-01
    • 1970-01-01
    • 2014-09-03
    • 2021-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多