{"id":1978,"date":"2015-12-13T17:52:33","date_gmt":"2015-12-13T16:52:33","guid":{"rendered":"http:\/\/denbeke.be\/blog\/?p=1978"},"modified":"2015-12-13T17:52:33","modified_gmt":"2015-12-13T16:52:33","slug":"swift-open-file-dialog-with-nsopenpanel","status":"publish","type":"post","link":"https:\/\/denbeke.be\/blog\/programming\/swift-open-file-dialog-with-nsopenpanel\/","title":{"rendered":"Swift: &#8220;Open file&#8230;&#8221; dialog with NSOpenPanel"},"content":{"rendered":"<p>For a simple Swift Mac app I needed to be able to give the user a modal to browse files and then display it in a textfield. Luckily Cocoa has the <a href=\"https:\/\/developer.apple.com\/library\/mac\/documentation\/Cocoa\/Reference\/ApplicationKit\/Classes\/NSOpenPanel_Class\/index.html\" target=\"_blank\">NSOpenPanel<\/a> which does exactly this. In this blogpost I give an example of how to use <code>NSOpenPanel<\/code>.<\/p>\n<h3>Example app<\/h3>\n<p>For this example I have a text field and a push button. A click on the button will load the dialog and afterwards the path of file the user selects will appear in that field.<\/p>\n<p><a href=\"http:\/\/denbeke.be\/blog\/programming\/swift-open-file-dialog-with-nsopenpanel\/attachment\/nsopenpanel-example-app\/\" rel=\"attachment wp-att-1981\"><img loading=\"lazy\" class=\"aligncenter wp-image-1981\" src=\"http:\/\/denbeke.be\/blog\/wp-content\/uploads\/2015\/12\/NSOpenPanel-example-app.png\" alt=\"NSOpenPanel example app\" width=\"437\" height=\"268\" srcset=\"https:\/\/denbeke.be\/blog\/wp-content\/uploads\/2015\/12\/NSOpenPanel-example-app.png 592w, https:\/\/denbeke.be\/blog\/wp-content\/uploads\/2015\/12\/NSOpenPanel-example-app-300x184.png 300w\" sizes=\"(max-width: 437px) 100vw, 437px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>In my example the field has the name <code>filename_field<\/code> in the <code>ViewController<\/code> class.\u00a0If you don\u2019t know how to create outlets for interface elements, read my earlier\u00a0<a href=\"http:\/\/denbeke.be\/blog\/programming\/creating-a-first-iphone-app-liveblog-in-swift\/\" target=\"_blank\">blogpost<\/a>.<\/p>\n<h3>\u201cOpen file\u2026\u201d dialog<\/h3>\n<p>To open the dialog we create the following function (in the <code>ViewController<\/code>):<\/p>\n<pre><code class=\"swift\">@IBAction func browseFile(sender: AnyObject) {\r\n    \r\n    let dialog = NSOpenPanel();\r\n    \r\n    dialog.title                   = \"Choose a .txt file\";\r\n    dialog.showsResizeIndicator    = true;\r\n    dialog.showsHiddenFiles        = false;\r\n    dialog.canChooseDirectories    = true;\r\n    dialog.canCreateDirectories    = true;\r\n    dialog.allowsMultipleSelection = false;\r\n    dialog.allowedFileTypes        = [\"txt\"];\r\n\r\n    if (dialog.runModal() == NSModalResponseOK) {\r\n        let result = dialog.URL \/\/ Pathname of the file\r\n        \r\n        if (result != nil) {\r\n            let path = result!.path!\r\n            filename_field.stringValue = path\r\n        }\r\n    } else {\r\n        \/\/ User clicked on \"Cancel\"\r\n        return\r\n    }\r\n    \r\n}<\/code><\/pre>\n<p>First we create a new instance of the <code>NSOpenPanel<\/code>, on which we set some properties (like which file type we allow to be chosen or wether the user can select directories or multiple files). Then we open the actual dialog: <code>dialog.runModal()<\/code>. We check for the return value of <code>runModal()<\/code> so we can ignore it if the user cancelled the modal, this also works for other modals like <code>NSSavePanel<\/code>.<br \/>\nWe extract the URL from the model once it is closed and store it in the <code>file_name<\/code> text field.<\/p>\n<h3>Toggling the dialog<\/h3>\n<p>The last thing we need to do is open the dialog once the user clicks on the \u201cSelect file\u201d button. To do so we click on the little circle at the left of the function declaration and drag the line to the button.<\/p>\n<p><a href=\"http:\/\/denbeke.be\/blog\/programming\/swift-open-file-dialog-with-nsopenpanel\/attachment\/nsopenpanel-button-click-example-xcode\/\" rel=\"attachment wp-att-1982\"><img loading=\"lazy\" class=\"aligncenter size-full wp-image-1982\" src=\"http:\/\/denbeke.be\/blog\/wp-content\/uploads\/2015\/12\/NSOpenPanel-button-click-example-Xcode.png\" alt=\"NSOpenPanel button click example Xcode\" width=\"958\" height=\"455\" srcset=\"https:\/\/denbeke.be\/blog\/wp-content\/uploads\/2015\/12\/NSOpenPanel-button-click-example-Xcode.png 958w, https:\/\/denbeke.be\/blog\/wp-content\/uploads\/2015\/12\/NSOpenPanel-button-click-example-Xcode-300x142.png 300w\" sizes=\"(max-width: 958px) 100vw, 958px\" \/><\/a><\/p>\n<p>Now we have a working OS X app with a browse file dialog. Build &amp; run it, everything should work!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>For a simple Swift Mac app I needed to be able to give the user a modal to browse files and then display it in a textfield. Luckily Cocoa has the NSOpenPanel which does exactly this. In this blogpost I give an example of how to use NSOpenPanel. Example app For this example I have [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[235],"tags":[125,149,257,258],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v15.6.2 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Swift: &quot;Open file...&quot; dialog with NSOpenPanel &ndash; DenBeke<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/denbeke.be\/blog\/programming\/swift-open-file-dialog-with-nsopenpanel\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Swift: &quot;Open file...&quot; dialog with NSOpenPanel &ndash; DenBeke\" \/>\n<meta property=\"og:description\" content=\"For a simple Swift Mac app I needed to be able to give the user a modal to browse files and then display it in a textfield. Luckily Cocoa has the NSOpenPanel which does exactly this. In this blogpost I give an example of how to use NSOpenPanel. Example app For this example I have [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/denbeke.be\/blog\/programming\/swift-open-file-dialog-with-nsopenpanel\/\" \/>\n<meta property=\"og:site_name\" content=\"DenBeke\" \/>\n<meta property=\"article:published_time\" content=\"2015-12-13T16:52:33+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/denbeke.be\/blog\/wp-content\/uploads\/2015\/12\/NSOpenPanel-example-app.png\" \/>\n<meta name=\"twitter:card\" content=\"summary\" \/>\n<meta name=\"twitter:creator\" content=\"@MthsBk\" \/>\n<meta name=\"twitter:site\" content=\"@MthsBk\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\">\n\t<meta name=\"twitter:data1\" content=\"2 minutes\">\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebSite\",\"@id\":\"https:\/\/denbeke.be\/blog\/#website\",\"url\":\"https:\/\/denbeke.be\/blog\/\",\"name\":\"DenBeke\",\"description\":\"Mathias Beke\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":\"https:\/\/denbeke.be\/blog\/?s={search_term_string}\",\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/denbeke.be\/blog\/programming\/swift-open-file-dialog-with-nsopenpanel\/#primaryimage\",\"inLanguage\":\"en-US\",\"url\":\"http:\/\/denbeke.be\/blog\/wp-content\/uploads\/2015\/12\/NSOpenPanel-example-app.png\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/denbeke.be\/blog\/programming\/swift-open-file-dialog-with-nsopenpanel\/#webpage\",\"url\":\"https:\/\/denbeke.be\/blog\/programming\/swift-open-file-dialog-with-nsopenpanel\/\",\"name\":\"Swift: \\\"Open file...\\\" dialog with NSOpenPanel &ndash; DenBeke\",\"isPartOf\":{\"@id\":\"https:\/\/denbeke.be\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/denbeke.be\/blog\/programming\/swift-open-file-dialog-with-nsopenpanel\/#primaryimage\"},\"datePublished\":\"2015-12-13T16:52:33+00:00\",\"dateModified\":\"2015-12-13T16:52:33+00:00\",\"author\":{\"@id\":\"https:\/\/denbeke.be\/blog\/#\/schema\/person\/386878f712fe3fe22227216f087772dc\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/denbeke.be\/blog\/programming\/swift-open-file-dialog-with-nsopenpanel\/\"]}]},{\"@type\":\"Person\",\"@id\":\"https:\/\/denbeke.be\/blog\/#\/schema\/person\/386878f712fe3fe22227216f087772dc\",\"name\":\"Mathias Beke\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/denbeke.be\/blog\/#personlogo\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/015ba35e6ce4f5859e3888ca99807575?s=96&d=mm&r=g\",\"caption\":\"Mathias Beke\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","_links":{"self":[{"href":"https:\/\/denbeke.be\/blog\/wp-json\/wp\/v2\/posts\/1978"}],"collection":[{"href":"https:\/\/denbeke.be\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/denbeke.be\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/denbeke.be\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/denbeke.be\/blog\/wp-json\/wp\/v2\/comments?post=1978"}],"version-history":[{"count":6,"href":"https:\/\/denbeke.be\/blog\/wp-json\/wp\/v2\/posts\/1978\/revisions"}],"predecessor-version":[{"id":1986,"href":"https:\/\/denbeke.be\/blog\/wp-json\/wp\/v2\/posts\/1978\/revisions\/1986"}],"wp:attachment":[{"href":"https:\/\/denbeke.be\/blog\/wp-json\/wp\/v2\/media?parent=1978"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/denbeke.be\/blog\/wp-json\/wp\/v2\/categories?post=1978"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/denbeke.be\/blog\/wp-json\/wp\/v2\/tags?post=1978"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}