70 votes

Les méthodes de délégués d'applications ne sont pas appelées dans iOS 13

J'utilise Xcode 11 et je crée une application pour iOS 13. Dans un nouveau projet que j'ai créé dans Xcode, certaines des méthodes de UIApplicationDelegate étaient manquantes, je les ai donc rajoutées dans le fichier de délégué de l'application. Le nouveau modèle pour un projet "Single View App" n'avait pas ces méthodes. Le problème est qu'aucune des méthodes du délégué n'est appelée, à part -application:didFinishLaunchingWithOptions: . Voici le délégué de mon application :

@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

186voto

nevan king Points 46410

iOS 13 propose une nouvelle façon d'envoyer les événements relatifs au cycle de vie des applications . Au lieu de passer par le UIApplicationDelegate ils passent par le UIWindowSceneDelegate qui est un UISceneDelegate sous-protocole. UISceneDelegate possède les méthodes de délégation importantes.

Cette modification vise à prendre en charge plusieurs fenêtres dans iOS 13. Il y a plus d'informations dans la session 212 de la WWDC 2019 " Introduction des fenêtres multiples sur l'iPad ". Les informations techniques commencent à l'adresse suivante vers 14h30 et est présenté par un homme avec des chaussures à talons très brillantes. La session courte 258 Conception de votre application pour plusieurs fenêtres propose également une excellente introduction à ce qui a changé.

Voici comment cela fonctionne : Si vous avez un " Manifeste de la scène de l'application "dans votre Info.plist et votre délégué d'application a une valeur de configurationForConnectingSceneSession la méthode UIApplication n'enverra pas de messages sur le cycle de vie de l'arrière-plan et du premier plan à votre délégué d'application. Cela signifie que le code de ces méthodes ne s'exécutera pas :

  • applicationDidBecomeActive
  • applicationWillResignActive
  • applicationDidEnterBackground
  • applicationWillEnterForeground

Le délégué de l'application recevra toujours le willFinishLaunchingWithOptions: y didFinishLaunchingWithOptions: de sorte que tout code dans ces méthodes fonctionnera comme avant.

Si vous voulez retrouver l'ancien comportement vous devez

  1. Supprimez l'entrée "Application Scene Manifest" du fichier Info.plist de l'application.
  2. Commentez ou supprimez le application:configurationForConnectingSceneSession:options: (ou la méthode Swift application(_:configurationForConnecting:options:) fonction)
  3. Ajoutez la propriété de la fenêtre à votre délégué d'application ( @property (strong, nonatomic) UIWindow *window; )

Vous pouvez également ouvrir le fichier SceneDelegate créé par Xcode et utiliser les nouvelles méthodes de cycle de vie qu'il contient :

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

Il est possible d'utiliser la nouvelle UIScene sans adopter la prise en charge des fenêtres multiples en réglant "Enable Multiple Windows" ("UIApplicationSupportsMultipleScenes") sur "NO" dans le fichier Info.plist (c'est la valeur par défaut pour les nouveaux projets). De cette façon, vous pouvez commencer à adopter la nouvelle API par petites étapes.

Vous pouvez constater que les noms des méthodes du délégué de la scène sont très proches de ceux du délégué de l'application. Une chose déroutante est que les méthodes de l'app delegate ne sont pas dépréciées, donc vous n'obtiendrez pas d'avertissement si vous avez les deux méthodes app delegate et scene delegate en place, mais une seule sera appelée.

D'autres choses qui UISceneDelegate prend le relais sont les activités des utilisateurs ( continueUserActivity: etc), la restauration de l'état ( stateRestorationActivityForScene: etc.), les questions de la barre d'état et les URL d'ouverture. (Je ne suis pas sûr qu'elles remplacent les méthodes des délégués de l'application). Il y a également des notifications analogues pour les événements du cycle de vie (tels que UISceneWillDeactivateNotification ).

De la session WWDC, quelques images pour vous :

Les équivalents des fonctions pour Swift :

enter image description here

Les responsabilités de la classe :

enter image description here

6voto

birdman Points 295

Ce fil de discussion m'a aidé :

Le contrôleur de vue répond aux notifications des délégués d'applications dans iOS 12 mais pas dans iOS 13.

Objectif 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];
}

2voto

DnV Points 45

Le cycle de vie des applications et des scènes n'est pas la même chose !

enter image description here

À mon avis, la désactivation des appels aux méthodes de changement d'état des applications (ainsi que l'envoi de notifications de changement d'état des applications lors du changement d'état de chaque scène) est une erreur, même s'il y avait une intention compréhensible de forcer les programmeurs à s'adapter au nouveau cycle de vie des scènes.

Voici un modèle de délégué de scène rétablissant les appels attendus des méthodes de changement d'état de l'application du délégué d'application :

@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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X