【问题标题】:Why is UIApplicationDelegate method `application(_:configurationForConnecting:options:)` not called reliably为什么不可靠地调用 UIApplicationDelegate 方法`application(_:configurationForConnecting:options:)`
【发布时间】:2020-12-10 16:07:29
【问题描述】:

问题:

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

文档说明:

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

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

转载:

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

  • Xcode 12 > 创建新项目 > iOS > 应用程序(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 的错误)

【问题讨论】:

    标签: ios swift appdelegate xcode12 uiscenedelegate


    【解决方案1】:

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

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

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

    案例 1:应用首次推出

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

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

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

    案例 3:应用重新启动

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

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


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

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

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

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

    【讨论】:

    • 基本上这是正确的。我提交了一个错误,Apple 告诉了我。
    • 感谢您的详细解释——我原本打算使用这种方法来设置场景 viewController 的依赖关系,但这显然不是一个好主意。实际上,我仍在寻找一种方法来正确在 iOS 上进行依赖注入,但这也是另一回事。
    • 啊,依赖注入。人们对“适当”的定义似乎千差万别!就我个人而言,我发现很多解决方案需要太多的管道,我写了一篇关于这个的博客文章 (luxmentis.org/ridiculously-simple-dependency-injection-in-swift)。但这是针对一堆全局变量的,听起来你想要每个场景的依赖项。不管你怎么做,也许你的场景代表是管理它们的正确地方?我目前正在尝试通过视图层次结构提供特定于上下文的依赖项——比如@EnvironmentObject,但我正在使用 UIKit,而不是 SwiftUI。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-10
    • 2011-12-02
    • 2018-03-19
    • 1970-01-01
    • 1970-01-01
    • 2020-10-02
    相关资源
    最近更新 更多