当基于场景的文档mac催化剂应用程序在应用程序重启时重新打开窗口时如何避免奇怪的行为?

Posted

技术标签:

【中文标题】当基于场景的文档mac催化剂应用程序在应用程序重启时重新打开窗口时如何避免奇怪的行为?【英文标题】:How to avoid strange behavior when scene-based document mac catalyst app reopens windows on app restart? 【发布时间】:2021-07-31 04:47:38 【问题描述】:

我一直在努力让 mac 催化剂应用程序的 mac 版本正常工作。这是一个基于场景、基于 DocumentBrowserViewController 的应用程序,在 iPad 上运行良好。在 Mac 上,它工作正常,除非您在屏幕上打开一个或多个文档窗口时关闭应用程序。当应用程序重新启动时,这些窗口会重新打开(除非用户在 Mac 系统偏好设置常规选项卡上选择了在退出应用程序时关闭窗口),并且由于使用了安全范围的书签,这些窗口将填充最后一个文档。但是,这些由 macOS(11.3.1 版)自动重新打开的窗口/场景不像在基于场景的应用程序中那样运行,它们就像基于 AppDelegate 的非基于场景的应用程序一样。我的意思是,当使用系统提供的新菜单项时,DocumentBrowserViewController 看起来应该如此,但是从浏览器中选择的文档会加载到系统提供的窗口之一中,替换那里的文档,而不是在新的窗口/场景。如果关闭这些窗口,然后选择新建菜单项,第一次选择文件时它没有打开,并且在日志中有一条消息:“场景破坏请求失败,错误:(null)”然后一条消息:

[Presentation] 尝试在 (来自 )上呈现 ,其视图不在窗口层次结构中。

下次您选择新建时,文档浏览器将打开,您可以选择一个文件并在新窗口/场景中正常打开。

我使用 self.present(controller, animated: true) 从文档浏览器视图控制器呈现文档视图控制器,并尝试了各种技巧,包括通过将文档视图控制器设置为窗口的 rootViewController 来呈现文档视图控制器。我几乎尝试了所有方法,但我确信根本问题是应用程序重新启动时系统打开的窗口不像基于场景的窗口那样表现。我面临着留下这种奇怪的行为,烦人的用户,可能会招致 App Store 拒绝,或者建议用户在应用程序退出一般偏好时打开关闭窗口,烦人的用户,或者复制代码库并使 mac 催化剂版本成为单一窗口, AppDelegate-based,non-scene-based,烦我,丢掉多窗口能力。

有没有其他人遇到过这个问题,有什么解决办法吗?听起来像是 Mac 催化剂还是 macOS 错误?

【问题讨论】:

【参考方案1】:

我还在开发一个基于 DocumentBrowserViewController 的应用程序,该应用程序支持多场景,并且遇到了很多关于 Catalyst 的问题。每次打开文档时,我都会看到“场景销毁请求失败并出现错误:(null)”错误,但它似乎不会影响应用程序的功能,所以我一直忽略它。

我还遇到了“视图不在窗口层次结构中”的问题,我想出了一个解决方法,可以让我可靠地呈现文档。在我从文档浏览器视图控制器中呈现文档的任何地方,我都会使用这段代码:

  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)
    

【讨论】:

1/ 我曾尝试过在您的 else 子句中呈现文档的方式,但没有想到像您那样将这两种方法结合起来。但是,我通过禁用关闭窗口按钮并强制用户使用工具栏按钮关闭窗口来解决问题。这允许文档正确关闭,无论它是在应用重新启动时自动打开还是在应用内打开。 2/ 问题是当应用程序关闭并打开窗口然后重新启动时,文档窗口会自动打开。当使用红色关闭窗口按钮关闭这些窗口时,场景退出活动并关闭窗口,而无需调用视图控制器 viewWillDisappear 方法。因此,正确保存文档的代码永远不会被调用,并且存在未知场景错误。通过强制用户点击我自己的关闭按钮(以及替换主菜单关闭项),窗口正确关闭并保存文档并且没有错误。 3/ 然而还是有片状。单击 Dock 中的文档列表不会打开该文档,并且有时打开最近的行为会很糟糕。并且仍然存在在重新打开的窗口时请求新场景的问题是在重新打开的窗口中加载文档而不是新窗口。但它和我现在能得到的一样好。 是的,红色的关闭按钮会在不通知视图控制器的情况下关闭窗口,因此您不能依赖它来保存更改。我正在使用 UIDocument 的自动保存功能,该功能在 Catalyst 上似乎可以正常工作,但是用户关闭了窗口。 我在单击 Dock 中的文档时也遇到了问题。在我的 AppDelegate 或 SceneDelegate 中似乎没有调用任何内容。通过将安全范围的书签存储在我的用户默认值中,我能够从菜单栏中打开最近的工作。 Catalyst 中基于文档的应用程序肯定存在很多问题。

以上是关于当基于场景的文档mac催化剂应用程序在应用程序重启时重新打开窗口时如何避免奇怪的行为?的主要内容,如果未能解决你的问题,请参考以下文章

为 mac 催化剂的 info.plist 文件中的键设置不同的值

为 mac 催化剂的 info.plist 文件中的键设置不同的值

Xcode 11 - 在催化剂 Swift 中禁用调整大小模式

Mac-catalyst - Mac 催化剂应用程序的最小窗口大小

Excel催化剂开源第5波-任务窗格在OFFICE2013中新建文档不能同步显示问题解决

将 Mac 催化剂二进制文件上传到 App Store 连接时出现问题