How to avoid strange behavior when scene-based document mac catalyst app reopens windows on app restart?

953 views Asked by At

I have been struggling to get the mac version of a mac catalyst app to work. This is a scene-based, DocumentBrowserViewController based app that works fine on the iPad. On the Mac, it works fine, except if you close the app when one or more document windows are left open on the screen. When the app is restarted, these windows reopen (unless the user has chosen on the Mac System Preferences general tab to close windows when quitting apps), and these windows are populated with the last document thanks to using security scoped bookmarks. However these windows/scenes reopened automatically by macOS (version 11.3.1) don't act like they are in a scene-based app, they act like an AppDelegate-based, non-scene-based app. What I mean is that when using the system provided New menu item, the DocumentBrowserViewController appears like it should, but a document chosen from the browser loads in one of the system provided windows, replacing the document that was there, instead of opening in a a new window/scene. If you close these windows, and then select the New menu item, the first time you select a file it doesn't open, and in the log there is a message: "Scene destruction request failed with error: (null)" and then a message:

[Presentation] Attempt to present <UINavigationController: 0x7f9fd9808e00> on <EP_Diagram.DocumentBrowserViewController: 0x7f9fd880a400> (from <EP_Diagram.DocumentBrowserViewController: 0x7f9fd880a400>) whose view is not in the window hierarchy.

The next time you choose New, the document browser opens and you can select a file and it opens fine in a new window/scene.

I present the document view controller from the document browser view controller using self.present(controller, animated: true), and have tried various hacks including presenting the document view controller by setting it to be the window's rootViewController. I have tried pretty much everything, but I am convinced that the fundamental problem is that the windows opened by the system at the app restart don't behave like scene-based windows should. I am faced with leaving this odd behavior in, annoying users and maybe courting App Store rejection, or recommending users turn on the close windows when apps quit general preference, annoying users, or duplicating the code base and making the mac catalyst version single window, AppDelegate-based, non-scene-based, annoying me and throwing away multi-window capabilities.

Has anyone else run into this problem and is there any solution? Does it sound like a mac catalyst or macOS bug?

1

There are 1 answers

6
nc2000 On

I'm also working on a DocumentBrowserViewController-based app with multi-scene support and have encountered a lot of issues with Catalyst. I'm seeing the "Scene destruction request failed with error: (null)" error every time I open a document, but it doesn't seem to impact the functionality of the app, so I've been ignoring it.

I also ran into the "view not in the window hierarchy" problem, and I came up with a workaround that allows me to reliably present documents. Any place where I'm presenting a document from my document browser view controller, I use this snippet of code:

  if(self.view.window != nil) {
        //This document browser's view is in the view hierarchy, so present as usual
        self.present(viewController, animated: animated, completion: completion)
    }
    else {
        //This document browser's view is not in the view hierarchy, find the view that is
        let topWindow = UIApplication.shared.connectedScenes.filter({$0.activationState == .foregroundActive})
            .map({$0 as? UIWindowScene})
            .compactMap({$0})
            .first?.windows
            .filter({$0.isKeyWindow}).first
        let rootController = topWindow?.rootViewController
        rootController?.present(viewController, animated: animated, completion: completion)
    }