2010-08-04 28 views
3

Je tente d'implémenter un comportement de terminaison personnalisé dans une application Cocoa. Normalement, lorsque mon application se termine normalement, il effectue un nettoyage de la base de données à l'exécution finale, puis se termine. Cela se produit à l'intérieur AppDelegate (délégué de NSApplication) chaque fois [NSApp terminate:aSender] est appelé:Comment implémenter NSApplication personnalisé terminate: comportement dans Cocoa?

- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender 
{ 
    // database cleanup... 
    return NSTerminateNow; 
} 

Si une erreur se produit lors de l'exécution (par exemple, le fichier de base de données a été supprimé), je vous présente l'erreur à l'utilisateur, et de leur donner la possibilité de Récupérer (remettre le fichier et réessayer) ou Quitter. Si Quit est sélectionné, je veux quitter l'application en ignorant le nettoyage de la base de données, car ce n'est plus possible. Essentiellement, je voudrais quelque chose comme ceci:

- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender 
{ 
    BOOL gracefulTermination = ...; 

    if (gracefulTermination == YES) 
    { 
     // Database cleanup.... 
    } 

    return NSTerminateNow; 
} 

Le problème, bien sûr, est d'obtenir la valeur pour gracefulTermination.

Existe-t-il un moyen de transmettre une variable personnalisée à NSApp lorsque terminate: est appelée, par exemple un infoDict, puis de la recevoir à l'intérieur de applicationShouldTerminate:?

Sinon, existe-t-il un meilleur moyen d'accomplir un comportement de terminaison personnalisé?


Pour autant que je sache, quand terminate: est appelé par un autre objet, cela se produit:

  1. [NSApp terminate:self]; est appelé par foo (auto alias).
  2. NSApp envoie son délégué: [aDelegate applicationShouldTerminate:self]; (auto est NSApp, pas foo). ADelegate reçoit le message et exécute applicationShouldTerminate: s'il est implémenté.

foo semble disparaître quelque part, et le temps aDelegate reçoit le message, il est parti pour de bon et ne NSApp apparaît comme l'expéditeur. Cela m'empêche de transmettre un infoDict à l'intérieur de foo, ou juste un infoDict, à aDelegate contenant le comportement personnalisé.


Je suis conscient qu'il est possible de sortir sans utiliser [NSApp terminate:...] avec quelque chose comme exit(). Bien que d'après ce que j'ai lu c'est mal vu que ce n'est pas casher pour Cocoa. De plus, cela empêcherait toute autre opération de nettoyage à l'intérieur de applicationShouldTerminate:, opérations qui ne devraient pas être ignorées même lors d'une sortie non gracieuse.

Répondre

3

La solution idéale serait de structurer votre application de sorte que le délégué de l'application puisse dire si elle est autorisée à se terminer.

En supposant que votre délégué d'application ne puisse pas accéder à cette information d'une autre manière (par exemple, l'objet déclenché par la terminaison affecte si cela peut arriver), cela semble la solution la plus simple: Sous-classe NSApplication, attribuez-lui une propriété terminationInfo et remplacez terminate: pour définir cette propriété et appeler super.

+0

Merci beaucoup Chuck. :) Tu me fais penser dans la bonne direction. J'ai fini par créer la variable 'gracefulTermination' dans AppDelegate. Je peux atteindre AppDelegate en utilisant [délégué NSApp], appelez [appDelegate setGracefulTermination: NO], suivi de [NSApp terminate: self]. Lorsque AppDelegate reçoit le message applicationShouldTerminate:, il saura comment se comporter maintenant. Je répondrai que votre réponse est correcte dans les 24 heures, à moins que quelqu'un d'autre en trouve une meilleure. Merci encore! –