Creating a macOS document based app with SwiftUI and the new App protocol

Have you already tried to create a macOS document based app with SwiftUI and the new App protocol? Well, there are some problems to solve esp. if you want to use menus focused on the currently open document.

In the old app cycle with AppDelegate / SceneDelegate you still had to use the storyboard to define the menu items and link them to your methods in your document class derived from NSDocument. Enabling and disabling of the menu item according to the open documents was automatically managed by the frameworks.

That’s not the case in the new App protocol of SwiftUI anymore. Instead, you can define your menus and menu items quite nicely in your App struct conforming to the new App protocol but there is no automatic link to the current document in focus.

I investigated a little bit about this problem and found this nice post (https://lostmoa.com/blog/AccessingTheDocumentIntheWindowCommands/) about passing the currently focused document to the menu commands.

This works fine for me and I have no need to implement the even more advanced window tracking strategy proposed in that blog post. With the above mentioned extension I have access to the currently focused document in my menu command. In the document struct I store a reference to my model and I can operate on that in the menu command. Very nice.

But I also want to use the undo manager in my menu command. Surprisingly, that’s not available in the command views (it’s set to nil) when you try to access it in the proposed way:

Too bad. Then I found this nice post (https://stackoverflow.com/questions/63273631/hosting-controller-when-using-ios-14-main/63276688#63276688) giving you access to the window the main content view belongs to.

The window do know the undo manager and I can store that in my document struct to give access to it in my command views:

As you see you can also do some other useful things there like saving the window sizes automatically with NSWindow.FrameAutsaveName(…) and getting the url of your document file. Even nicer.

Btw: The undoManager?.setActionName(…) seems to be broken or not implemented here as of Big Sur / Xcode 12.5 / SwiftUI 2. It has no effect.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.