SwiftUI on macOS: PDF Help book

This article has a source code supplement. To read that in parallel, open this link in a separate window or tab so you can follow this account with its full source code.

Substantial apps for macOS need Help books, even if they’re hardly ever read. While tooltips and contextual snippets of aid can be valuable, a proper Help book is an essential guide and reference for both users and the developer. When I built my first toy SwiftUI app I was excited that it came with a Help menu command, then groaned when I saw what it displayed.

I’ve still not been able to work out how to create a view that SwiftUI will substitute for this default, so the primary aim of this article is to explain how to implement a proper Help book in a SwiftUI app for macOS.

I’ve also long since abandoned trying to create Help books in the format preferred by NSHelpManager. There’s only one GUI tool that I know of to do that, Help Crafter, and while I still use that to maintain my older Help books, these days I prefer to put brief guides into Rich Text, and full-blown Help books and reference guides in PDF. The secondary aim of this article is therefore to show how to display a PDF document in a SwiftUI View.

Little Helper App

At an app level, the main WindowGroup is for the regular app window, ContentView; the secondary Window is for the Help book, and will only be opened on demand. The Help menu command to do that is configured in a separate Commands structure.

Menu Commands

Although the app Help command is already used in a SwiftUI app, there seems to be no way to redirect its action to display a custom Help window. Thus, the only way to do that is to replace the existing command with a new one. As that needs to open the Help window, access to that has to be enabled in its Environment, as shown.

Main window

This is just the default ContentView from the SwiftUI app template.

Help view

This is where all the work is done. As SwiftUI still doesn’t support any form of PDF view, this has to be accessed from Quartz, as a PDFKitView.

The first struct here handles the creation of a new PDFView containing the PDF document named LittleHelperHelp.pdf, added to the app bundle, as the Help book. As the Help book is read-only, there’s no need to provide any code to update the PDF. This PDFKitView is then displayed in the HelpView. Finally, HelpView is set to be previewed in Xcode.

This Help book appears to work as well as it does when implemented in AppKit using Interface Builder.

As in so many cases, the solution in SwiftUI isn’t complex or extensive, but discovering each of the ingredients necessary and getting them to work together remains largely undocumented and opaque.

Summary

At an App level, a secondary Window such as a Help view is only opened on demand.
To add or replace menu commands, define them in a CommandGroup.
Implement a functional Help command by replacing the existing command.
Display PDF in a Quartz PDFView.
Load a PDF Help book from within the app bundle.
To preview a secondary Window, add a Preview.