简体   繁体   中英

Opening NSDocument based app loads two windows

I have a simple NSDocument based app that has two text fields (Imagine a git differ). When I open my file, it opens two windows with my file name. Everything works great on the first window. The second's UI is empty with the same file name.

override func makeWindowControllers() {
    // Returns the Storyboard that contains your Document window.
    let storyboard = NSStoryboard(name: NSStoryboard.Name("Main"), bundle: nil)
    let windowController = storyboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier("Document Window Controller")) as! NSWindowController
    self.addWindowController(windowController)
}

override func read(from data: Data, ofType typeName: String) throws {

    if let fileString = String(data: data, encoding: String.Encoding.utf8) {

        makeWindowControllers()

        guard let vc = windowControllers.first?.contentViewController as? ViewController else {
            throw NSError(domain: NSOSStatusErrorDomain, code: unimpErr, userInfo: nil)
        }

        guard let inputString = String(data: data, encoding: .utf8) else {
            throw NSError(domain: NSOSStatusErrorDomain, code: unimpErr, userInfo: nil)
        }

        let doc = JsonConverter().convertToJSONFrom(string: inputString)

        if let a = doc["a"] as? String {
            vc.leftTextView.string = a
        }

        if let b = doc["b"] as? String {
            vc.rightTextView.string = b
        }

    } else {
        throw NSError(domain: NSOSStatusErrorDomain, code: unimpErr, userInfo: nil)
    }
}

主界面

I don't get where the second one (on the right) is coming from.

edit: I just noticed that if I double click a saved file, I get this error which oddly enough, does NOT fire from any of those NSErrors in the read() function.

Fwiw, Open from the menu is what I was referring to above.

edit 2: Correction. 'Sometimes' it opens two windows. But even when it does that, both are empty. What I don't get is that this read function is so simple, there isn't much to go wrong. It feels like it's all going sideways under the hood.

双击文件时出错。

I don't get where the second one (on the right) is coming from.

It looks like it's probably coming from your read() function, which calls makeWindowControllers() . From the documentation :

This method is called by the NSDocumentController open... methods, but you might want to call it directly in some circumstances.

When a document is opened, it is of course also read, so makeWindowControllers() is being called twice: once by the document's built-in open behavior, and once by your read() override.

Correction. 'Sometimes' it opens two windows. But even when it does that, both are empty.

Perhaps you've got an occasional error that prevents the document to even getting to the read() call.

if I double click a saved file, I get this error

That supports the idea that something is going wrong before you even get to read() . You can find out easily enough by putting a log message in read() and checking the console for that message after a case where only one window opens. Also, do you have any application(open...) methods overridden in your app delegate? Perhaps one of those is responsible for the error.

Update:

After messing around a bit with a simple document-based project, I found that NSDocument does indeed call makeWindowControllers() for you, but it does so after it calls read() . A breakpoint in your read() method will show that there are no view controllers because makeWindowControllers() hasn't been called yet. Here's my read() method:

override func read(from data: Data, ofType typeName: String) throws {
    // makeWindowControllers();
    guard let text = String(bytes: data, encoding: .utf8) else { return }
    self.content = text
}

If I uncomment the call to makeWindowControllers() , I get the same symptom that you're asking about: two windows open, and only one of them shows the content. If I create a new document, though, I only get one window because the read() method never gets called.

So this app is very basic at this point. View controller has a couple outlets and sets the text in NSTextViewDelegate's textDidChange function. But that's it. App delegate default, then the Document class. If I don't call makeWindowControllers then windowControllers is empty. If I call it, then I have 1 controller, which is what I use to update the UI. Not really sure how to get around that.

You're trying to do too much in your read() method. NSDocument is very MVC-oriented, and you can think of the document as a kind of controller — it ties the views and the data together. The read() method is meant to let you read the data, and the views aren't created until after that. I think that's probably because the data might determine what kind of view to create. My document class has a content property that's just a string, and read() just grabs the data from the file and sticks it in the string. In my case, makeWindowControllers() gets called for me automatically, and my override uses content to set up the window:

override func makeWindowControllers() {
    // Returns the Storyboard that contains your Document window.
    let storyboard = NSStoryboard(name: NSStoryboard.Name("Main"), bundle: nil)
    let windowController = storyboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier("Document Window Controller")) as! WindowController
    windowController.text = self.content
    self.addWindowController(windowController)
}

Also, if I comment out the call to makeWindowControllers, it never gets called when I open a file. Logging proves that its only called once with the manual call and zero times without it.

I don't have a good explanation for this if your log statement is in makeWindowControllers() . It's inconsistent with what I'm seeing, so I'd ask you to a) check your work and b) add more information here, either in a comment or in your question. Again, I'm seeing makeWindowControllers() being called without the need to call it explicitly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM