Is there a sample app for UIDocument using UIScene for MacCatalyst?

I've spent the last 1.5 years of my life trying to figure out how to make a uidocument-based app work with UIScene for MacCatalyst. Has anyone succeeded? Are there examples anywhere? Any guides or tutorials? Apple doesn't even have a template in Xcode! Apple's documentation is either fractured, missing or inaccurate. I always get crazy errors. The #1 problem I have is auto-re-opening a doc after the app quits. I get blank windows where the doc used to be, but on top of that I get an open-dialog box. Debugging says the os sees my sessions, but then throws them away and doesn't tell me why... When I quit the app, saving fails in sceneWillResignActive (with no explanation I can find), closing the document fails in sceneDidDisconnect(...) (with no explanation I can find), after the app quits the debugger stays running while profiler says my app is in the background, and then the watch dog timer expires and kills my app. I'm not doing any background work... I don't have any crazy long-running processes.
At first I thought "oh, let's not write new features in AppKit, UIKit is soooo much easier, I'll just re-write the whole darn thing in MacCatalyst and then I can write new features for both Mac & iPad", but noooo. It's the fundamentals I can't get to work in MacCatalyst. The drag & dropping? works perfectly. But docs don't save - sometimes, and they don't reopen, but it all works perfectly on an iPad.
:Picard facepalm:.
I'm about to just give up trying to make apps entirely - and I've been doing it for 14 years!
Answered by benspratling4 in 690853022

The bugs preventing UIDocument-based UIScene-based MacCatalyst apps from working properly have been fixed in the macOS 12 betas a few weeks ago. Still don't work right in macOS 11.6.

It appears the system is throwing the sessions away because the watch dog timer killed the app.

After 5 seconds after hitting command-q, I see this in the console.
[Lifecycle] Watchdog: App took too long to enter the background-only state. Exiting immediately! (5.0s)
[Lifecycle] Watchdog timeout. Exiting immediately. (App took too long to enter the background-only state.)
[Assert] App took too long to enter the background-only state.

When I pull up the Console console, I get a serious of incomprehensible excuses for not saving the document.
Code Block
UIDocument unrecoverable error with description: You don’t have permission to save the file “Untitled.txt” in the folder “Documents”. reason: You don’t have permission.

Code Block
Failed to recover from error with description: You don’t have permission to save the file “Untitled.txt” in the folder “Documents”. reason: You don’t have permission.

Why not? I opened it? I have read/write permissions in the entitlements.
Code Block
Sandbox: MyAppName(5631) deny(1) file-read-data /Users/myusername/Documents/mydocument.txt

Why? If I close the doc by dismissing the view controller and calling .close directly, it saves successfully. So how did I lose permissions to save my work just because I'm quitting the app? Seems like a major major major design flaw in the OS.

Filed a DTS incident... It turns out that the os does not correctly handle typing command-q, whereas it does "correctly" handle using the mouse to select quit from the application menu. How does it not handle that correctly? The sandbox does not know that the file is still 'ok' to be written to. So writing out contents to autosave works, but when UIDocument goes to replace the original file with the version it wrote to the temp dir, it gets a sandbox error. This bug is still in macOS 11.2.2.

I know, I know, isn't it just a UIKeyCommand? Well, it is, but actually it's hacked somehow, because the quit command selector is terminate:, which is not a documented selector in UIKit. And if you try to make your own, it just crashes. And using a Mac obj-c plug-in to access appkit to call terminate: on the nsapplication instance doesn't do any of the things the uiscenes need done.

BUT, when I click the menu command for quit instead of the shortcut, it goes ahead and proactively discards my scene sessions, thus meaning there's never going to be a scene to restore when the app launches again. Which, I think is definitely not the expectation, but it's better than opening blank windows and never giving me a session to restore.

A year and a half of my life.... a year and a half. That's how long I've been re-writing apps to UIKit so I could more easily and more rapidly release apps than using AppKit. And the OS literally just never worked.
Hi Ben, sorry to read you’re having so much trouble.

On the Mac, scenes are restored only if the user unchecks “Close windows when quitting an app” in the General panel in System Preferences (this option defaults to checked). Otherwise, it is expected that a new scene is created when you relaunch your app.

Which callback are you using to trigger saving your document?
Doh! I used to remember that setting existed, probably 11 months ago when I first started investigating why this was failing. Changed that and I got the sessions coming back.

Still no idea why the doc browser gives a posix error 22 "invalid argument" when I try to ".revealDocument(at:" the url of the doc during my restoration. Can I open the document anyway?
Removing all debug print() statements from scene/document code seems to have fixed the watchdog timer issues.
I'm also attempting a document based catalyst app, trying to get it to work with UIScene hasn't been going well. I'm struggling with opening a document from Finder in to a new window. If possible could you share the basics of your app delegate and scene delegate? I've turned on multiple window support but can't seem to get the document URL through to the scene.
I'm also struggling with porting a document-based, scene-based iPad app to the Mac with Mac Catalyst. I've been struggling with the same problem as DavidNZ. When I double click in Finder to open a document sometimes it opens, and sometimes just a blank window opens. Same with the Open Recent menu item. Sometimes it works and sometimes it doesn't. I have a feeling this is a threading issue, but I'm not sure what needs to be done asynchronously in my code to make it work.

I can also confirm the issue with Cmd-Q vs selecting Quit from the menu. In the first case changes aren't saved, but they are with the second. I'll try updating the change count on viewDidDisappear or one of the other lifecycle events to fix this, but it really seems to be a bug in catalyst.

I think I bit off more than I can chew here. I'm tempted to copy the code base and eliminate scenes, or painfully duplicate the app in AppKit. Ugh.

Hey Ben, just to weigh in on the saving-when-quitting issue as I ran into the same today — I think you'll need a documentURL.startAccessingSecurityScopedResource() as you're saving, which should make it all write correctly. Other than that, just calling your save method from a regular on-disconnect background task should work. Hope that helps

Accepted Answer

The bugs preventing UIDocument-based UIScene-based MacCatalyst apps from working properly have been fixed in the macOS 12 betas a few weeks ago. Still don't work right in macOS 11.6.

Is there a sample app for UIDocument using UIScene for MacCatalyst?
 
 
Q