xcode 在 iOS 13 中未调用应用程序委托方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/56508764/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 10:57:50  来源:igfitidea点击:

App delegate methods aren't being called in iOS 13

iosxcodeuiapplicationdelegateios13uiscenedelegate

提问by nevan king

I am using Xcode 11 and building an app for iOS 13. In a new project I created in Xcode some of the UIApplicationDelegate methods were missing so I added them back into the app delegate file. The new template for a "Single View App" project was missing the methods. The problem is that none of the delegate methods are getting called except -application:didFinishLaunchingWithOptions:. Here is my app delegate:

我正在使用 Xcode 11 并为 iOS 13 构建应用程序。在我在 Xcode 中创建的新项目中,缺少一些 UIApplicationDelegate 方法,因此我将它们重新添加到应用程序委托文件中。“单一视图应用程序”项目的新模板缺少方法。问题是除了-application:didFinishLaunchingWithOptions:. 这是我的应用程序委托:

@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

回答by nevan king

iOS 13 has a new way of sending app lifecycle events. Instead of coming through the UIApplicationDelegatethey come through the UIWindowSceneDelegatewhich is a UISceneDelegatesub-protocol. UISceneDelegatehas the important delegate methods.

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

This change is to support multiple windows in iOS 13. There's more information in WWDC 2019 session 212 "Introducing Multiple Windows on iPad". The technical information starts at around 14:30and is presented by a man with very sparkly high-tops. The shorter session 258 Architecting Your App for Multiple Windowsalso has a great introduction to what's changed.

此更改是为了在 iOS 13 中支持多个窗口。 WWDC 2019 session 212“ Introducing Multiple Windows on iPad”中有更多信息。技术信息从14:30 左右开始,由一位穿着闪亮高帮的男士提供。较短的会话 258为多个 Windows 构建您的应用程序也对更改的内容进行了很好的介绍。

Here's how it works:If you have an "Application Scene Manifest" in your Info.plist and your app delegate has a configurationForConnectingSceneSessionmethod, the UIApplicationwon't send background and foreground lifecycle messages to your app delegate. That means the code in these methods won't run:

这是它的工作原理:如果您的 Info.plist 中有一个“应用程序场景清单”并且您的应用程序委托有一个configurationForConnectingSceneSession方法,UIApplication则不会向您的应用程序委托发送后台和前台生命周期消息。这意味着这些方法中的代码不会运行:

  • applicationDidBecomeActive
  • applicationWillResignActive
  • applicationDidEnterBackground
  • applicationWillEnterForeground
  • applicationDidBecomeActive
  • applicationWillResignActive
  • applicationDidEnterBackground
  • applicationWillEnterForeground

The app delegate will still receive the willFinishLaunchingWithOptions:and didFinishLaunchingWithOptions:method calls so any code in those methods will work as before.

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

If you want the old behaviour backyou need to

如果你想恢复旧的行为,你需要

  1. Delete the "Application Scene Manifest" entry from the app's Info.plist
  2. Comment or delete the application:configurationForConnectingSceneSession:options:method (or the Swift application(_:configurationForConnecting:options:)function)
  3. Add the window property back to your app delegate (@property (strong, nonatomic) UIWindow *window;)
  1. 从应用程序的 Info.plist 中删除“应用程序场景清单”条目
  2. 注释或删除application:configurationForConnectingSceneSession:options:方法(或 Swiftapplication(_:configurationForConnecting:options:)函数)
  3. 将 window 属性添加回您的应用程序委托 ( @property (strong, nonatomic) UIWindow *window;)

Alternatively, open the SceneDelegate file that Xcode made and use the new lifecycle methods in there:

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

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

It's possible to use the new UIScenelifecycle stuff without adopting multiple window support by setting "Enable Multiple Windows" ("UIApplicationSupportsMultipleScenes") to "NO" in the Info.plist (this is the default for new projects). This way you can start adopting the new API in smaller steps.

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

You can see that the scene delegate method names are a close match for the app delegate ones. One confusing thing is that the app delegate methods aren't deprecated so you won't get a warning if you have both app delegate and scene delegate methods in place but only one will be called.

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

Other things that UISceneDelegatetakes over are user activities (continueUserActivity:etc), state restoration (stateRestorationActivityForScene:etc), status bar questions and opening URLs. (I'm not sure if these replace the app delegate methods). It also has analogous notifications for the lifecycle events (like UISceneWillDeactivateNotification).

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

From the WWDC Session, some images for you:

来自 WWDC Session 的一些图片供您参考:

The function equivalents for Swift:

Swift 的等价函数:

enter image description here

在此处输入图片说明

The class responsibilities:

班级职责:

enter image description here

在此处输入图片说明

回答by birdman

This thread helped me:

这个线程帮助了我:

View controller responds to app delegate notifications in iOS 12 but not in iOS 13

视图控制器响应 iOS 12 中的应用程序委托通知,但不响应 iOS 13

Objective C:

目标 C:

if (@available(iOS 13.0, *)) {
    [[NSNotificationCenter defaultCenter] addObserver:self 
          selector:@selector(appWillResignActive:) 
          name:UISceneWillDeactivateNotification object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self 
          selector:@selector(appDidBecomeActive:) 
          name:UISceneDidActivateNotification object:nil];

}
else {
    [[NSNotificationCenter defaultCenter] addObserver:self 
          selector:@selector(appWillResignActive:) 
          name:UIApplicationWillResignActiveNotification object:nil];


    [[NSNotificationCenter defaultCenter]addObserver:self
          selector:@selector(appDidBecomeActive:)
          name:UIApplicationDidBecomeActiveNotification
                                              object:nil];
}