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.