【问题标题】:App delegate methods aren't being called in iOS 13iOS 13 中未调用应用程序委托方法
【发布时间】:2019-10-23 19:31:44
【问题描述】:

我正在使用 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

【问题讨论】:

    标签: ios xcode uiapplicationdelegate ios13 uiscenedelegate


    【解决方案1】:

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

    此更改是为了在 iOS 13 中支持多个窗口。在 WWDC 2019 session 212 "Introducing Multiple Windows on iPad" 中有更多信息。技术信息从around 14:30 开始,由一位穿着非常闪亮的高帮鞋的男士提供。较短的会话 258 Architecting Your App for Multiple Windows 也很好地介绍了变化。

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

    • applicationDidBecomeActive
    • applicationWillResignActive
    • applicationDidEnterBackground
    • applicationWillEnterForeground

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

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

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

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

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

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

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

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

    来自 WWDC 会议,为您提供一些图片:

    Swift 的等效函数:

    类职责:

    【讨论】:

    • 这是否意味着我必须将 SceneDelegate.h 文件添加到我的项目中?我遇到了同样的问题,但仍然不知道如何使它工作。
    • @Miguel 这个建议确实适用于使用 Xcode 11 创建的新项目。如果您的项目是使用旧 Xcode 创建的,它应该仍然可以工作
    • 谢谢,但它根本没有。有趣的是,当我不调试我的应用程序时,它可以完美运行。
    • 是的,确实如此,但老实说,我只是创建了一个新项目并将我所有的源代码文件添加到其中。我已经尝试修复它太久了,甚至在 Apple 论坛上解释了这种情况,没有人知道发生了什么。典型的 XCode 错误行为。
    • 还有“为多个 Windows 构建应用程序”(developer.apple.com/videos/play/wwdc2019/258)
    【解决方案2】:

    这个帖子帮助了我:

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

    目标 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];
    }
    

    【讨论】:

      【解决方案3】:

      应用程序和场景生命周期不是一回事!

      在我看来,禁用应用程序状态更改方法的调用(以及在更改每个场景的状态时发送应用程序状态更改通知)是一个错误,即使有一个可以理解的意图迫使程序员适应新的场景生命周期。

      这是一个场景委托模板,用于恢复应用程序委托的应用程序状态更改方法的预期调用:

      @available(iOS 13.0, *)
      class SceneDelegate: UIResponder, UIWindowSceneDelegate {
          
          func sceneWillResignActive(_ scene: UIScene) {
              
              if !UIApplication.shared.connectedScenes.contains(where: { $0.activationState == .foregroundActive && $0 != scene }) {
                  UIApplication.shared.delegate?.applicationWillResignActive?(.shared)
              }
          }
          
          
          func sceneDidEnterBackground(_ scene: UIScene) {
              
              if !UIApplication.shared.connectedScenes.contains(where: { $0.activationState == .foregroundActive || $0.activationState == .foregroundInactive }) {
                  UIApplication.shared.delegate?.applicationDidEnterBackground?(.shared)
              }
          }
          
          
          func sceneWillEnterForeground(_ scene: UIScene) {
              
              if !UIApplication.shared.connectedScenes.contains(where: { $0.activationState == .foregroundActive || $0.activationState == .foregroundInactive }) {
                  UIApplication.shared.delegate?.applicationWillEnterForeground?(.shared)
              }
          }
          
          
          func sceneDidBecomeActive(_ scene: UIScene) {
              
              if !UIApplication.shared.connectedScenes.contains(where: { $0.activationState == .foregroundActive && $0 != scene }) {
                  UIApplication.shared.delegate?.applicationDidBecomeActive?(.shared)
              }
          }
      }
      

      SceneDelegate.swift

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-07-16
        • 2020-02-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多