ios - iOS 13 中未调用应用程序委托(delegate)方法

标签 ios xcode uiapplicationdelegate ios13 uiscenedelegate

我正在使用 Xcode 11 并为 iOS 13 构建应用程序。在我在 Xcode 中创建的新项目中,缺少一些 UIApplicationDelegate 方法,因此我将它们添加回应用程序委托(delegate)文件中。 “单一 View 应用程序”项目的新模板缺少方法。问题是除了 -application:didFinishLaunchingWithOptions: 之外,没有任何委托(delegate)方法被调用。这是我的应用委托(delegate):

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    NSLog(@"application:didFinishLaunchingWithOptions:");
    return YES;
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
    NSLog(@"applicationDidEnterBackground:");
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
    NSLog(@"applicationWillEnterForeground:");
}
#pragma mark - UISceneSession lifecycle

- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options {
    return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
}

- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet<UISceneSession *> *)sceneSessions {
}

@end

最佳答案

iOS 13 有一种发送应用生命周期事件的新方法。它们不是通过 UIApplicationDelegate 来的,而是通过 UIWindowSceneDelegate 来的这是一个 UISceneDelegate子协议(protocol)。 UISceneDelegate 具有重要的委托(delegate)方法。

此更改是为了支持 iOS 13 中的多个窗口。在 WWDC 2019 session 212“Introducing Multiple Windows on iPad”中有更多信息。技术信息开始于 around 14:30由一位穿着非常 Shiny 的高帮鞋的男士呈现。较短的 session 258 Architecting Your App for Multiple Windows也很好地介绍了更改内容。

它是这样工作的:如果您的 Info.plist 中有一个“Application Scene Manifest”并且您的应用委托(delegate)有一个configurationForConnectingSceneSession方法,UIApplication 不会向您的应用委托(delegate)发送后台和前台生命周期消息。这意味着这些方法中的代码将不会运行:

  • applicationDidBecomeActive
  • applicationWillResignActive
  • applicationDidEnterBackground
  • applicationWillEnterForeground

应用程序委托(delegate)仍会收到 willFinishLaunchingWithOptions:didFinishLaunchingWithOptions: 方法调用,因此这些方法中的任何代码都将像以前一样工作。

如果您想要恢复旧行为,您需要

  1. 从应用程序的 Info.plist 中删除“Application Scene Manifest”条目
  2. 注释或删除 application:configurationForConnectingSceneSession:options: 方法(或 Swift application(_:configurationForConnecting:options:)函数)
  3. 将窗口属性添加回您的应用委托(delegate) (@property (strong, nonatomic) UIWindow *window;)

或者,打开 Xcode 创建的 SceneDelegate 文件并使用其中的新生命周期方法:

- (void)sceneDidBecomeActive:(UIScene *)scene {
}
- (void)sceneWillResignActive:(UIScene *)scene {
}
... etc

通过在 Info.plist 中将“Enable Multiple Windows”(“UIApplicationSupportsMultipleScenes”)设置为“NO”(这是默认设置),可以在不采用多窗口支持的情况下使用新的 UIScene 生命周期内容用于新项目)。通过这种方式,您可以以更小的步骤开始采用新的 API。

您可以看到场景委托(delegate)方法名称与应用程序委托(delegate)方法名称非常匹配。一件令人困惑的事情是,应用程序委托(delegate)方法并未被弃用,因此如果您同时拥有应用程序委托(delegate)和场景委托(delegate)方法但只会调用一个方法,您将不会收到警告。

UISceneDelegate 接管的其他事情是用户事件(continueUserActivity: 等)、状态恢复(stateRestorationActivityForScene: 等)、状态栏问题和打开网址。 (我不确定这些是否取代了应用程序委托(delegate)方法)。它还具有生命周期事件的类似通知(如 UISceneWillDeactivateNotification)。

来自 WWDC session 的一些图片:

Swift 的等效函数:

enter image description here

类职责:

enter image description here

关于ios - iOS 13 中未调用应用程序委托(delegate)方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56508764/

相关文章:

iphone - 如何从 AppDelegate 获取 navController。

ios - 从 didFinishLaunchingWithOptions 终止应用程序

objective-c - iPhone/iPad itunes 库读取权限?

ios - Apple 说 "Your iOS Distribution Certificate expiring"我需要做什么

ios - 一对多关系查询中的核心数据

xcode - 如何构建命令行实用程序

ios - 无法在 iOS 11 以下的 Web View 中更改用户代理

ios - UIAlertController 按钮代表不会触发(在 Modally Segue 中)

c++ - 在 C++ 中计算大数

iOS - 应用程序委托(delegate) - 使用 CLLocationManager 调用 didBecomeActive