【问题标题】:How to get Main Window (App Delegate) from other class (subclass of NSViewController)?如何从其他类(NSViewController 的子类)获取主窗口(App Delegate)?
【发布时间】:2011-10-01 12:39:09
【问题描述】:

我正在尝试从其他类(即 NSViewController 的子类)更改我的 Windows 内容。我正在尝试下面的代码,但它什么也没做。

[NSApplication sharedApplication]mainWindow]setContentView:[self view]]; //code in NSViewController

[NSApplication sharedApplication]mainWindow] // returns null

我尝试添加

[window makeMainWindow];

在 App Delegate 类中,但无济于事。

我错过了什么吗?

附:另外我正在使用下面的代码来调用我班级中的任何委托函数,

 [(appDelegate *) [[NSApplication sharedApplication]delegate]MyMethod];

但我想知道是否有更好的方法,但不导入委托类。像这样的

[[NSApplication sharedApplication]delegate]MyMethod];

(它给出警告)

【问题讨论】:

    标签: objective-c macos cocoa


    【解决方案1】:

    对于mainWindow method the docs say

    如果应用程序的 nib 文件尚未完成加载、接收器未处于活动状态或应用程序处于隐藏状态,此方法可能会返回 nil。

    我刚刚创建了一个快速测试应用程序,并放置了以下代码:

    NSLog(@"%@", [[NSApplication sharedApplication] mainWindow]);
    

    进入我的applicationDidFinishLaunching:aNotification 方法,并进入我连接到应用程序主窗口中的按钮的操作方法。

    在启动时,mainWindow 为 nil,但当我单击按钮时(在一切启动并运行并显示后),mainWindow 不再为 nil。

    NSApplication 提供了其他可能对您有用的方法:

    • - windows - 所有窗口的数组;
    • – keyWindow - 给出正在接收键盘输入(或 nil)的窗口;
    • – windowWithWindowNumber: - 返回与窗口编号对应的窗口 - 如果您知道要替换其内容的窗口编号,则可以使用它;
    • – makeWindowsPerform:inOrder: - 向每个窗口发送一条消息 - 您可以使用它来测试每个窗口,看看它是否是您感兴趣的窗口。

    关于在delegate 上调用方法,你所说的给出警告对我来说很好。例如,这可以在没有警告的情况下工作:

    NSLog(@"%@", [[[NSApplication sharedApplication]delegate] description]);
    

    您收到的警告究竟是什么?您是否尝试调用不存在的方法?

    【讨论】:

    • 非常感谢。我只有一个窗口。所以可能我会使用 windows 来进入 Array,并会使用 Array 中的第一个对象。关于委托的方法,您是否从不同的类(如视图控制器)尝试过?当我调用它时,它可以正常工作,但它会发出警告,该委托可能不会响应该方法。
    • 我明白你现在关于代表电话的意思了。不幸的是,[[NSApplication sharedApplication] delegate] 消息总是会返回一个 NSApplicationDelegate 类型的对象。如果您想向它发送特定于您的应用程序委托的消息,则必须将其转换为您的应用程序委托。您可能想将此作为一个单独的问题提出?
    • 我认为唯一的方法是将 NSApplicationDelegate 转换为特定的委托,并将其导入类中。谢谢。
    • 还有另一种方式!你可以 [[NSApplication sharedApplication]delegate]performSelector:@selector(selectorName)];如果您知道委托中的选择器名称,则无需包含 appdelegate 标头和类型转换。这会奏效。
    • 在 Swift Playground 中怎么样?如何获得非零主窗口?
    【解决方案2】:

    与 MacOS 的斗争才发现了这一点。

    苹果的报价:

    主窗口

    房产

    应用程序的主窗口。 (只读)

    讨论

    当应用程序的故事板或 nib 文件尚未完成加载时,此属性中的值为 nil。当应用不活动隐藏时,它也可能为 nil。

    如果您的应用程序中只有一个窗口(这是最常用的情况),请使用下一个代码:

    NSWindow *mainWindow = [[[NSApplication sharedApplication] windows] objectAtIndex:0];
    

    保证它不会是零,如果应用程序有窗口。

    【讨论】:

    • 我正在评论 3 年前的一个问题,但这似乎也不起作用。它不应该返回一些东西吗,因为代码进入的 ViewController 在它尝试获取窗口时已经完成加载?
    • 您将此代码粘贴到 viewDidLoad 中它应该可以工作。当然,如果您的应用程序中没有窗口,那么它将为零。
    • 感谢您的回复。它在 tableView 方法之一中,因为它是 NSTableView 的委托。所以我不知道为什么它不起作用,窗口显示内容。
    • 我很确定你不能保证它不会是 nil。
    • 当然,如果应用程序没有任何窗口,它将是 nil...相应地编辑答案。
    【解决方案3】:

    如果尚未设置 window 属性,请尝试延迟操作,直到应用完成加载,如下所示:

    [myObject performSelector:@selector(theSelector) withObject:nil afterDelay:0.1];
    

    【讨论】:

      【解决方案4】:

      获取主窗口(如果存在)的 Swift 风格的方法

      应用程序主窗口

      guard let window = NSApplication.shared.mainWindow,
      else {
          // handle no main window present
      }
      // ... access window here
      

      应用程序窗口数组

      let windowArray: [NSWindow] = NSApplication.shared.windows
      guard windowArray.count > 0 else {
          // hand case where no windows are present
      }
      let window = windowArray[0]
      // ... access window here
      

      【讨论】:

        猜你喜欢
        • 2012-03-15
        • 2016-11-08
        • 1970-01-01
        • 2019-11-25
        • 1970-01-01
        • 2023-03-25
        • 1970-01-01
        • 2011-02-26
        • 1970-01-01
        相关资源
        最近更新 更多