8

问题:

我发现有关 AppDelegate 方法的一些意外行为application(_:configurationForConnecting:options:)

该文档指出:

UIKit 在创建新场景之前不久调用此方法。

我希望每次启动应用程序时都是这种情况。
当我第一次启动我的应用程序时确实调用了该方法,但是对于所有后续启动,它不是.

复制:

我有一个非常简单的测试用例可以重现:

  • Xcode 12 > 创建新项目 > iOS > App (UIKit/Storyboard)
  • 在方法中添加调试语句,AppDelegate如下所示:
      // from Apple's sample project:
      func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
          // Called when a new scene session is being created.
          // Use this method to select a configuration to create the new scene with.
          print("I was called!").  // <--- debugging statement
          return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
      }
    
  • 运行应用程序 > “我被叫了!” 在控制台中打印
  • 再次运行应用程序 > 没有打印任何内容。

问题:

为什么application(_:configurationForConnecting:options:)在第二次启动时不被调用?
(这是预期的行为,如果是,为什么/它是 Apple 的错误)

4

1 回答 1

18

这似乎是预期的行为,一旦您了解正在发生的事情就有意义,但它没有记录在案。我刚刚花了一些相当痛苦的时间来追根究底。哦,苹果。

要知道的关键是,当您重新启动应用程序时,之前运行的窗口会恢复。

(这也有助于记住一个应用程序可以有多种类型的窗口——每一种都由一个场景配置表示——这就是为什么你可能首先实现这个委托方法的原因。)

案例一:App 首次上线

该应用程序不知道要在窗口中放置哪种类型的场景,并调用application(_:configurationForConnecting:options:)以查找。到目前为止,一切都如我们所料。(如果你不实现这个委托方法,它只是回退到你Info.plist的场景清单中的第一个合适的条目,如果它有的话。)

案例 2:创建新窗口(适用于支持多窗口的应用程序)

(例如,通过拖动 iPad 上的停靠图标)。该应用程序也不知道在此窗口中放置什么。与案例 1 相同。

案例 3:应用重新启动

操作系统想要恢复您的 Windows。为此,它会记住您上次打开的窗口的场景配置。惊喜!它知道要在窗口中放置哪些场景,并且不会询问您的应用程序委托。它只是继续使用记住的配置创建场景。

对于考虑在应用程序启动时创建窗口的可怜的开发人员来说,这是令人困惑的。但是,如果您考虑在启动时恢复窗口而不是创建窗口 - 即使只有一个 - 它开始有意义。


现在,如果你想重置一些东西,以便忘记你的窗口并在下次启动时调用你的委托方法:

  • 对于 iOS,删除应用程序
  • 对于 Catalyst,删除应用的容器

注 1: 在 Catalyst 中,似乎只有第一个窗口在重新启动时恢复,但其他行为与上述相同。现在已经观察到这不是真的。也许是不一致的。

注意2:您还可以恢复窗口的内容,而不仅仅是它们的类型,使用UIWindowSceneDelegateand UISceneSession.stateRestorationActivity,但那是另一回事了。

于 2020-10-21T05:10:42.450 回答