2

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?

HangarRash
  • 7,314
  • 5
  • 5
  • 32
David Mann
  • 91
  • 3

1 Answers1

1

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)
    }
nc2000
  • 161
  • 9
  • 1/ I had tried the manner of presenting the document in your else clause, but did not think of combining the two methods like you did. However I sort of solved the problem by disabling the close window button and forcing the user to close the window with a toolbar button. This allows the document to close properly whether it is a opened automatically when the app restarts or it is opened within the app. – David Mann Jun 05 '21 at 15:42
  • 2/ The problem is the document windows opened automatically when the app is closed with a window open and then restarted. When those windows are closed with the red close window button, the scene resigns active and closes the window without ever calling the view controller viewWillDisappear method. So the code there to properly save the document never gets called, and there is an unknown scene error. By forcing the user to hit my own close button (as well as replacing the main menu Close item) the windows close properly and the document is saved and there are no errors. – David Mann Jun 05 '21 at 15:42
  • 3/ There is still flakiness however. Clicking on the document list in the Dock doesn't open the document, and sometimes Open Recent behaves badly. And there is still the issue that requesting a new scene when there is a reopened window loads the document in the reopened window and not a new window. But it's as good as I can get it for now. – David Mann Jun 05 '21 at 15:46
  • 1
    Yes, the red close button shuts down the window without notifying the view controller, so you can't rely on that for saving changes. I'm using UIDocument's autosave functionality, which seems to work correctly on Catalyst however the user closes out the window. – nc2000 Jun 05 '21 at 17:30
  • 1
    I'm also seeing issues when clicking on a document in the Dock. Nothing seems to get called in my AppDelegate or SceneDelegate. I was able to get Open Recent working from the Menu bar by storing security-scoped bookmarks in my user defaults. There are definitely a lot of issues with document-based apps in Catalyst. – nc2000 Jun 05 '21 at 17:32
  • I too got Open Recent working by storing security scoped bookmarks, having the user select the working directory and storing it in user defaults. Fortunately the app got approved and is in the App Store. I was worried Apple would not like my disabling the close window button, but the main complaint they had was I used the term "tap" rather than "click" in the user interface. I'm still not happy with the user experience, but it's the best I can do given the problems with Catalyst and document/scene-based apps. – David Mann Jun 06 '21 at 02:32