Opening files in macOS

I'm writing a macOS app for the first time in many years, and I'm having trouble remembering how to let the user open a file from disk. I know I need to use FileManager along with NSOpenPanel. Could someone point me to a simple tutorial (or even some simple code) that illustrates how to do this?

Accepted Reply

Here is a typical example of IBAction associated to open menu item.


    @IBAction func openDossier(_ sender: NSMenuItem) {
       
        let openPanel = NSOpenPanel()

        openPanel.title = NSLocalizedString("List file", comment: "enableFileMenuItems")    // If need to localise
        openPanel.message = NSLocalizedString("List file", comment: "enableFileMenuItems")   
        openPanel.prompt = NSLocalizedString("Open », comment: "enableFileMenuItems")  
        openPanel.canChooseDirectories = false  // if you want to select only files at the end
        openPanel.canCreateDirectories = true 
        openPanel.canChooseFiles = true  

        let token = FileManager.default.ubiquityIdentityToken
        openPanel.canDownloadUbiquitousContents = token != nil
        openPanel.canResolveUbiquitousConflicts = false

        // filter file type
        openPanel.allowedFileTypes = ["xxxx"] // If you want to filter on file type
        openPanel.begin() { (result) -> Void in
            if result == NSApplication.ModalResponse.OK {
                let newDocURL = openPanel.url!) / save the URL somewhere
                // Do what you need with the file
               
            }       // result == NSModalResponseOK
        }       // beginWithCompletionHandler
    }

Replies

Here is a typical example of IBAction associated to open menu item.


    @IBAction func openDossier(_ sender: NSMenuItem) {
       
        let openPanel = NSOpenPanel()

        openPanel.title = NSLocalizedString("List file", comment: "enableFileMenuItems")    // If need to localise
        openPanel.message = NSLocalizedString("List file", comment: "enableFileMenuItems")   
        openPanel.prompt = NSLocalizedString("Open », comment: "enableFileMenuItems")  
        openPanel.canChooseDirectories = false  // if you want to select only files at the end
        openPanel.canCreateDirectories = true 
        openPanel.canChooseFiles = true  

        let token = FileManager.default.ubiquityIdentityToken
        openPanel.canDownloadUbiquitousContents = token != nil
        openPanel.canResolveUbiquitousConflicts = false

        // filter file type
        openPanel.allowedFileTypes = ["xxxx"] // If you want to filter on file type
        openPanel.begin() { (result) -> Void in
            if result == NSApplication.ModalResponse.OK {
                let newDocURL = openPanel.url!) / save the URL somewhere
                // Do what you need with the file
               
            }       // result == NSModalResponseOK
        }       // beginWithCompletionHandler
    }

It worked! Thanks very much: you saved me a lot of time.

Now I have another question. I put the @IBAction code you recommended into my ViewController file, since it's the view controller that displays the file text in its view. Everything was working as expected.


But it seems this @IBAction really belongs in the AppDelegate file. So I'm wondering how I give my view controller the url of the file I want to open. Do I need to set up an NSNotification? Or is there a more elegant solution?

You can either:


- save the URL you get in openDossier into a global var (that's the simplest and usually what I do)

- create a var in the controller where you need the url and update this var from openDossier through use of a delegate ; I find it overcomplex in this case.