【问题标题】:Initial app launch from storyboard fails to call NSDocument init从情节提要启动的初始应用程序无法调用 NSDocument init
【发布时间】:2017-10-26 12:54:59
【问题描述】:

我使用 Xcode 模板编写了一个带有故事板的 macOS 文档类型应用程序,并且在某个地方,初始应用程序启动和文档之间的关联与预期的模式不同,因此没有一个 NSDocument 初始化程序我希望在应用程序首次启动时被调用(但此后每个新窗口都会被调用)。

我已经对所有四个记录在案的 NSDocument 初始化器进行了子类化,如下所示:

public class Simulation: NSDocument {

        override init() {
        debugPrint("--------------------\(#file)->\(#function) called")
        super.init()
    }

    init(contentsOf: URL, ofType: String) throws {
        debugPrint("--------------------\(#file)->\(#function) called")
        fatalError()
    }

    init(for: URL?, withContentsOf: URL, ofType: String) throws {
        debugPrint("--------------------\(#file)->\(#function) called")
        fatalError()
    }
    convenience init(type: String) throws {
        debugPrint("--------------------\(#file)->\(#function) called, type: \(type)")
        self.init()
    }

    public override class func autosavesInPlace() -> Bool {
        debugPrint("--------------------\(#file)->\(#function) called")
        return false
    }
}

应用程序启动时,没有一个 init 显示 debugPrint 输出。应用程序窗口在启动时成功创建,没有明显文档关联。

但是,我注意到一些我无法解释的非常奇怪的行为:

  1. 虽然我没有看到任何 init 调用,但 autosavesInPlace 在应用程序在文档的某个实例上启动后被调用了 3 次
  2. 当我使用 cmd-N(即 File->New 和因此 newDocument())创建一个新文档时,autosavesInPlace 又被调用了 3 次,然后执行文档初始化!
  3. 我从来没有看到对 makeWindowControllers() 的调用

我的 NSDocument 子类名为 Simulation。异常似乎是在最初的启动中有一些绕过 Simulation.init 的魔法,但此后每次创建文档+窗口时都调用它。

这是我的问题:

  1. 为什么初始启动不调用 Simulation.init()?
  2. 当只有那个初始的、看似部分构造的窗口时,autosavesInPlace 如何找到要调用的模拟实例?

【问题讨论】:

  • autosavesInPlace 是一个类方法,它在类上调用,而不是在实例上调用。你实现applicationShouldOpenUntitledFile了吗?
  • 很糟糕,我错过了 autosavesInPlace 作为类函数。我猜这不是我的日子。无论如何,我还没有实现applicationShouldOpenUntitledFile。我在应用程序委托中这样做了,并在我在那里时为其合作伙伴applicationOpenUntitledFile 提供了一个存根,并运行了应用程序。两者都没有被调用 - 当我启动应用程序时没有调用,也没有调用 cmd-N。
  • @Willeke - 具体来说,当我启动应用程序时,我看到了这个(在 VC 中添加了打印)(我无法格式化为代码!)` "VC.swift->init(coder:调用”“VC.swift->viewDidLoad() 调用”“VC.swift->viewWillAppear() 调用”“VC.swift->viewDidAppear() 调用”` 但是,使用 cmd-N 我得到这个:`“模拟。 swift->init(type:) 调用,类型:Effie.Simulation" "Simulation.swift->init() 调用" "Simulation.swift->makeWindowControllers() 调用" "VC.swift->init(coder: 调用" “VC.swift->viewDidLoad() 调用” “VC.swift->viewWillAppear() 调用” “VC.swift->viewDidAppear() 调用”`
  • 我们无法猜测故事板中未识别的变化是什么。创建一个新的测试项目并进行比较。休息一下init(type:)
  • 我也猜不出来,并且初始窗口没有调用 init(type:) - 这就是我无法弄清楚的原因!

标签: swift macos storyboard init nsdocument


【解决方案1】:

在您的故事板中,确保您的窗口控制器及其内容视图控制器都未选中 Is Initial Controller,并且在属性检查器中将 Presentation 设置为 Multiple

选中Is Initial Controller 将导致应用程序在任何NSDocument/NSDocumentController“魔术”发生之前实例化一个窗口控制器。应该选择 Presentation: Multiple 以保持连贯性,尽管它可能不会真正产生影响。

另外,请确保您的文档类型在 Info.plist 中正确设置,尤其是 NSDocumentClass 键(应包含 $(PRODUCT_MODULE_NAME).Simulation)。

我相信您关于autosavesInPlace 的问题已经在 cmets 中得到解答……

【讨论】:

  • 就是这样 - 我确实在窗口上设置了Is Initial Controller。我从来没有发现过 - 我会在 viewWillAppear 中强制执行文档,这当然会导致打开/新对话框不出现。非常感谢您的帮助。
  • 非常感谢,请确保未选中“Is Initial Controller”?
猜你喜欢
  • 2013-11-10
  • 2012-08-09
  • 2016-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多