简体   繁体   中英

How to open programmatically a document in a NSDocument macOS app?

I'm new to macOS programming and I created a NSDocument app project to learn this architecture.

All works correctly, I can create a document, save it, and open one from Finder using standard UI controls.

I'm trying to save and open a document programmatically. I implemented these two actions. Saving works fine, but read don't work. Edit: I mean that the document window is not shown.

I would be very grateful if somebody could tell me what I'm doing wrong.

// this seems to work because the document is created and I can open it with drag and drop over the app
@IBAction func saveButtonPressed(_ sender: Any) {
    let directoryURL = FileManager.default.urls(for: .desktopDirectory, in: .userDomainMask).first // or .applicationSupportDirectory

    let docURL = URL(string:"MyFile.docuExperiments", relativeTo:directoryURL)

    if (try? document.write(to: docURL!, ofType: "com.myCompany.docuExperiments")) != nil {
    } else {
        print("An error occured")
    }
}

// the document window is not shown
@IBAction func loadButtonPressed(_ sender: Any) {
    let directoryURL = FileManager.default.urls(for: .desktopDirectory, in: .userDomainMask).first // or .applicationSupportDirectory

    let docURL = URL(string:"MyFile.docuExperiments", relativeTo:directoryURL)

    if (try? document.read(from: docURL!, ofType: "com.myCompany.docuExperiments")) != nil {
    } else {
        print("An error occured")
    }
}

This seems to work.

Save the document:

@IBAction func saveButtonPressed(_ sender: Any) {
    let directoryURL = FileManager.default.urls(for: .desktopDirectory, in: .userDomainMask).first

    let docURL = URL(string:"MyFile.docuExperiments", relativeTo:directoryURL)

    if (try? document.write(to: docURL!, ofType: "com.myCompany.docuExperiments")) != nil {
    } else {
        print("An error occured")
    }
}

Open the document:

@IBAction func loadButtonPressed(_ sender: Any) {
    let documentController = NSDocumentController.shared()

    let directoryURL = FileManager.default.urls(for: .desktopDirectory, in: .userDomainMask).first

    let docURL = URL(string:"MyFile.docuExperiments", relativeTo:directoryURL)

    documentController.openDocument(withContentsOf: docURL!, display: true) {
        // completionHandler (NSDocument?, Bool, Error?)
        (document, documentWasAlreadyOpen, error) in
        if error != nil
        { print("An error occured")
        } else {
            if documentWasAlreadyOpen
            {
                print("documentWasAlreadyOpen: true")
            } else {
                print("documentWasAlreadyOpen: false")
            }
        }
    }

}

(thanks to Willeke for the tips).

NSDocument manages the display of a document from a URL. It's NSDocumentController that should be used to initiate the opening & saving of documents (although, as you have discovered, there's nothing stopping NSDocument from writing a copy of a document).

From the docs :

NSDocumentController Creates and Manages Documents

An app's NSDocumentController object manages the documents in an app. In the MVC design pattern, an NSDocumentController object is a high-level controller. It has the following primary responsibilities:

  • Creates empty documents in response to the New item in the File menu
  • Creates documents initialized with data from a file in response to the Open item in the File menu
  • Tracks and manages those documents
  • Handles document-related menu items, such as Open Recent

(my emphasis)

IF you want to use your own routine, you need to subclass NSDocumentController and put your open routine in there. But it already has all of that logic, so really all you need to do is hook your button to the target of File -> Open, which will be func beginOpenPanel(completionHandler: @escaping ([URL]?) -> Void) in the default NSDocumentController . So there is no need to do so. Just read the NSDocumentController docs (linked above)

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