Some snippets of code for your Swift apps
Hi! While programming in Swift I have accumulated many code snippets. Some of them are mine and some of them come from the internet. Here I’m sharing 5 tiny quality-of-life snippets. Hopefully you will find them useful.
1. (Cocoa) Accessing NSWindow from NSViewController
1 2 3 4 5 6 7 8 9 10 | extension NSViewController { var window: NSWindow? { for window in NSApp.windows { if window.contentViewController == self { return window } } return nil } } |
This snippet adds a window variable to NSViewController. It requires the window to exist (eg. be in NSApp.windows, in most cases that will be true) and that there is only one window with the specified view controller. It will return the window with the view controller on which it is called.
2. Checking if path leads to a directory
1 2 3 4 5 6 7 | extension FileManager { func isDirectory(path: String) -> Bool { var isDirectory: ObjCBool = false self.fileExists(atPath: path, isDirectory: &isDirectory) return isDirectory.boolValue } } |
This is a simple wrapper around FileManager.fileExists()
as an extension to FileManager
that checks whether a path provided as a string leads to a directory.
3. Safely accessing an array
1 2 3 4 5 6 7 8 9 | extension Array { subscript(safely index: Int) -> Element? { if index < self.endIndex && index >= 0 { return self[index] } else { return nil } } } |
This snippet adds a subscript to arrays. It checks whether index is within the array’s range then returns an element or nil depending on the check. You can use it like this:
1 2 | let array = ["a", "b", "c"] let value = array[safely: 2] // returns Optional("c") |
This might save you few lines of code for checking and force you to handle the edge case without crashing the app.
4. (SwiftUI) Web view wrapper
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | struct WebView: NSViewRepresentable { /// URL of current page. If changed, WebView will change it into the new URL. @Binding var url: URL private var onLoadStart: (WKWebView) -> () private var onLoadFinish: (WKWebView) -> () /// A WKWebView instance, which is used to render WebView, and which can be used to control it thanks to classes being passed by reference. private var wkWebView: WKWebView /// Accepts a binding to an URL, WKWebView instance, which can be used to control WebView and onLoadStart and onLoadFinish which will run when WebView starts or finishes loading a webpage. init(url: Binding<URL>, wkWebView: WKWebView = WKWebView(), onLoadStart: ((WKWebView) -> ())? = nil, onLoadFinish: ((WKWebView) -> ())? = nil) { self.wkWebView = wkWebView self._url = url if let onLoadStart = onLoadStart { self.onLoadStart = onLoadStart } else { self.onLoadStart = { _ in } } if let onLoadFinish = onLoadFinish { self.onLoadFinish = onLoadFinish } else { self.onLoadFinish = { _ in } } } func makeNSView(context: Context) -> WKWebView { wkWebView.navigationDelegate = context.coordinator wkWebView.load(URLRequest(url: url)) return wkWebView } func updateNSView(_ nsView: WKWebView, context: Context) { nsView.load(URLRequest(url: url)) } func makeCoordinator() -> Coordinator { Coordinator(onLoadStart: onLoadStart, onLoadFinish: onLoadFinish) } class Coordinator: NSObject, WKNavigationDelegate { let onLoadStart: (WKWebView) -> () let onLoadFinish: (WKWebView) -> () init(onLoadStart: @escaping (WKWebView) -> (), onLoadFinish: @escaping (WKWebView) -> ()) { self.onLoadStart = onLoadStart self.onLoadFinish = onLoadFinish } func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) { onLoadStart(webView) } func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { onLoadFinish(webView) } } } |
This pretty lengthy snippet adds a simple SwiftUI wrapper around WKWebView
(which needs to be imported). It only requires a binding to a url, which will be loaded. In more complex cases, you can pass onLoadStart
and onLoadFinish
handlers which will run when the web view starts and finishes loading and a WKWebView
class instance. Since in Swift classes are passed by reference, you can use this instance in your view to control the web view (go back, forward, etc).
5. (Cocoa) Showing an alert
1 2 3 4 5 6 7 8 9 10 11 12 13 | func showAlert(message: String, informative: String, buttons: [String] = [], completionHandler: @escaping (NSApplication.ModalResponse) -> () = { _ in }) { DispatchQueue.main.async { let alert = NSAlert() alert.messageText = message alert.informativeText = informative buttons.forEach { alert.addButton(withTitle: $0) } let result = alert.runModal() completionHandler(result) } } |
Once again, a wrapper. It wraps NSAlert
in one function so that you don’t need to rewrite this code. It accepts a message and informative text which will be used on the alert. It also optionally accepts a list of button titles which will be added to the alert. It also runs asynchronously on the main thread, so it works even when run in another thread. Here I’d like to add that you can use NSAlert.accessoryView
to create alerts with custom views, for example I did something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | func showChoicePrompt(message: String, informativeText: String, buttons: [String], completionHandler: @escaping (String?) -> Void) { let alert = NSAlert() alert.addButton(withTitle: "OK") alert.addButton(withTitle: "Cancel") alert.messageText = message alert.informativeText = informativeText let popUp = NSPopUpButton(frame: NSRect(x: 0, y: 0, width: 200, height: 24)) popUp.addItems(withTitles: buttons) alert.accessoryView = popUp let response: NSApplication.ModalResponse = alert.runModal() if response == NSApplication.ModalResponse.alertFirstButtonReturn { completionHandler(popUp.selectedItem?.title) } else { completionHandler(nil) } } |
which creates an alert with a pop up button for selecting a value.
As a sidenote, if you are dealing with many snippets of various types (like these ones), CodeMenu can help you organize, access and use their full potential.