A Mac app Template in SwiftUI
Notes from a new dev.
I (mostly) wrote a book on writing a Mac app using AppKit. It covered the basics of app development for the Mac. I then abandoned Mac development in favour of learning SwiftUI and creating iOS apps instead. iOS apps are nice and shiny and have all the fancy toys while Mac apps are basic and functional. What would you pick?
Then I had another play with the Mac and, this time, I decided to have a go at creating apps using SwiftUI. I went in to this with the simple though that "it's SwiftUI, how different can it be?". Turns out it has the same 'feel' but the details are very different.
I set about learning what I could and quickly found that the majority of training materials for the Mac deal with AppKit and anything that dealt with SwiftUI was basic and lacking in detail. Some of it is good and some of it seems to stop short of describing the really useful stuff. I followed a couple of tutorials but they barely scratched the surface of things like preferences screens, about box popups and menus.
So, I decided to create a sample Mac app and to document how I created it and to try to go into a little more detail than I had found on the Web. This was the inspiration for this book and the sample project that goes with it.
Key Learning Points
Whats in the book?
I've based the book on the AppKit version to a large extent, but with the content geared towards SwiftUI. Not everything is possible in SwiftUI, so I have dropped back to AppKit only where necessary.
The Default Project
The default project describes the purpose of the document and walks you through creating a basic Mac app. It goes on to explain some of the issues with the default template that Apple give us and proposes some fixes for issues like the default window size, the window title and getting the app to close when the last window is closed.
Dialogs
The dialogs section deals with two items that were glossed over in the tutorials I read; the About Box and the Settings screen. Some tutorials briefly cover settings but I have gone more in-depth, covering multi-tab settings and settings that are not simple check boxes.
The Main Window
The section on the main window takes the standard "Hello World" window to a NavigationStackView, customising the sidebar to set minimum width, add a sidebar toolbar and create a view model to allow the sidebar to communicate with the detail view. We then customise the detail view to add a toolbar, illustrating where icons will be positioned and how it affects the window title.
Interim cleanup
I next have a short section on refactoring the project. At this point, we have made a lot of changes to the default project that XCode created for us and the code is in need of some cleanup. I work through some structure changes to make the code cleaner and, hopefully, more understandable. I also introduce SwiftLint as a useful tool to enforce coding standards and walk through some basic fixes to our code.
Menus
The Menus section was difficult to create. Very few of the tutorials I worked through did more than create basic menus that did nothing useful. Most were menus that printed something to the debug console and did nothing else. In the real world, this information, while useful as a start point, is unrealistically simplified.
I expand upon the usual tutorials to show deleting standard menus, adding new menu items and I provide a mechanism that can connect a menu item to code in the currently active view model. There may be better ways to do this, but what I have gives a clean link between clicking on a menu item and having code run in the view mode of the current view. I have not seen that happen in any of the tutorials I have followed.
File Handling
For this section, I am having to drop more into AppKit to achieve the display of a file section window and a file save-as window. There are no native components in SwiftUI for displaying these windows, so we have to interface with NSOpenPanel and NSSavePanel. I encapsulate these into a helper struct which should be straight forward to extend in a 'real' application.
Notifications
There are a tremendous number of notifications running around the system at any one time. Being able to hook into existing ones, such as when our window is about to close, allows us to handle situations that are not easily dealt with using pure SwiftUI. In this section we explore what is necessary to handle system notifications and to create our own when appropriate.
Helpers
The final section deals with a number of topics that, while useful, are not large enough to warrant a chapter of their own. In this section, we cover three topics;
- Logging - a simple class that provides simplistic logging
- Pasteboard - demonstrates the use of the pasteboard
- Alerts - provides a simple alert message framework that can be used in views or view models.
Updates
Feb 2024 I have expanded the Notifications section to plug in the use of .onReceive to handle the user notifications rather than handling it ourselves in the view model initialisation and tear down.
Where is it?
Can I have a copy?
The book and it's associated project are available on GitHub in my Mac Template repo. It's going to be under continual development until I decide I have enough functionality built in to the template to make it useful as a starter project. If you just want to take a look at the document itself, it' in the docs folder (or you can click here for it)..
Testimonials
Am I really any good?
Don't take my word for my abilities, take a look at other peoples opinions about me.