11
votes

Pourquoi soulevez-vous une nsexception qui ne ressort pas ma candidature?

Le problème strong>

J'écris une application de cacao et je souhaite soulever des exceptions qui placera l'application bruyamment. p>

J'ai les lignes suivantes dans mon application Délégué: p>

-(void)applicationDidFinishLaunching:(NSNotification *)note
    // ...
    [self performSelectorInBackground:@selector(crash) withObject:nil];
}

-(void)crash {
    [NSException raise:NSInternalInconsistencyException format:@"This should crash the application."];
    abort();
}


0 commentaires

6 Réponses :


2
votes

J'ai posté cette question et répondez comme je la souhaite que quelqu'un m'aurait dit cela, oh il y a environ un an:

exceptions levées sur le thread principal sont pris par NSApplication.

I Skim Lisez les docs sur NsException Fin à la fin, sans mentionner cela que je peux me rappeler. La seule raison pour laquelle je sais cela est à cause du fantastique cacao dev:

http://www.cocoadev.com/index.pl?ExceptionHandling

la solution. Je suppose.

J'ai un démon sans interface utilisateur qui fonctionne presque entièrement sur le fil principal. Je devrai transférer l'application entière pour exécuter des threads d'arrière-plan, à moins que quelqu'un d'autre ne puisse suggérer un moyen d'arrêter Nsaplication capturer uniquement les exceptions que je jette. Je suis à peu près sûr que ce n'est pas possible.


4 commentaires

Je pense que vous avez manqué une page. développeur.apple.com/mac/library/documentation/cocoa/conceptu al / ... " Remarque: Les exceptions sur le fil principal d'une application de cacao n'augmentent généralement pas au niveau du gestionnaire d'exceptions non capturies car L'objet d'application global attrape toutes ces exceptions. " ... Le corps principal de la page mentionne également la solution David Gelhar a parlé de.


Oui, évidemment très paresseux, lecture de ma part. :) Merci d'avoir souligné cela. Il y a même une boîte autour de le souligner. Duh.


Bonjour John, j'ai posté une "réponse" ci-dessous dans une tentative de comprendre le problème plus clairement. Des idées?


Peu importe, je pense que j'ai trouvé une solution à mon problème. J'ai mis à jour ma "réponse" en conséquence.



3
votes

Peut-être que vous pouvez utiliser NSSETUNTERDEXCEPTHANDLER ou Créez une catégorie sur NSApplication qui remplace - ReportException: , comme suggéré à http://www.cocoadev.com/index.ploStackTraces


1 commentaires

Excellente suggestion, David. J'ai lu cette page des lots il y a quelques mois, mais je n'ai pas essayé la catégorie de catégorie Nsappllication pour une raison quelconque. J'aurai un coup de travail de cette façon, car il est beaucoup plus facile que d'essayer d'obtenir tout mon code en cours d'exécution sur les threads de fond!



10
votes

Mise à jour - 16 nov. 2010: strong> Il existe des problèmes avec cette réponse lorsque des exceptions sont jetées à l'intérieur des méthodes d'ibaction. Voir cette réponse à la place:

Comment peut-on J'arrête Hitoolbox d'attraper mes exceptions? p>


Ceci se développe sur David Gelhar's Strong> réponse, et le lien qu'il a fourni. Vous trouverez ci-dessous la façon dont je l'ai fait en remplaçant la méthode -ReportException de NSAPPLication: code>. Premièrement, créez une catégorie d'exceptions pour NSApplication (FYI, vous devez ajouter un acronyme de 2 à 3 lettres avant «Exceptions de l'exception» pour réduire le risque d'afflichage de noms): P>

NsApplication + ExceptionnelHandling.h fort> p> xxx pré>

nsappllication + exceptionsHandling.m strong> p> xxx pré>


second, à l'intérieur Délégué de Nsapplication, j'ai procédé à ce qui suit: p>

Appdelegate.m strong> p> xxx pré>

plutôt que d'utiliser le NSAPP's Terminez: , vous pouvez appeler quitter () code> à la place. Terminez: CODE> est plus cocoa-casher, bien que vous puissiez ignorer votre ApplicationsHouldterminate: code> dans l'événement Une exception a été lancée et simplement un crash difficile avec Quitter ( ) code>: p> xxx pré>


Chaque fois qu'une exception est lancée, sur le fil principal em>, et que ce n'est pas attrapé ni détruit, votre Le gestionnaire d'exception personnalisé non capturé sera désormais appelé à la place des NSAPPLICATION. Cela vous permet de planter votre application, entre autres choses. P>


Mise à jour: strong> h2>

Il semble y avoir un petit problème dans le code ci-dessus. Votre gestionnaire d'exception personnalisé ne «frappera» et ne fonctionnera qu'après que Nsaplication ait fini d'appeler toutes ses méthodes de délégation. Cela signifie que si vous faites du code de configuration à l'intérieur ApplicationWillFinishLaunching: strong> ou ApplicationDiderFinishLaunching: strong> ou éveilléfromnib: strong>, le gestionnaire d'exception NSApplication par défaut semble être dans -Jouez jusqu'à ce que cela soit complètement initialisé. p>

Qu'est-ce que cela signifie que c'est si vous faites ceci: p> xxx pré>

Votre exceptionnel (forte> won ' t obtenir l'exception. Nsapplication va, et ça va simplement le loger. P>

Pour résoudre ce problème, mettez simplement tout code d'initialisation à l'intérieur d'un @ try / @ catch / @ enfin code> bloquer et vous pouvez appeler votre Personnalisé ExceptionnelHandler STROND>: P>

- (void)applicationWillFinishLaunching:(NSNotification *)aNotification
{
    NSSetUncaughtExceptionHandler(&exceptionHandler);

    @try
    {
        MyClass *myClass = [[MyClass alloc] init];   // throws an exception during init...
    }
    @catch (NSException * e)
    {
        exceptionHandler(e);
    }
    @finally
    {
        // cleanup code...
    }
}


1 commentaires

Cette solution est trop complexe. La réponse de George ci-dessous est la bonne façon de le faire: "[[[Nsuserdefault StandardAserdefault] registerDefault



1
votes

Je suis en train de comprendre cela: Pourquoi la méthode de la catégorie suivante sur NSApplication conduire à une boucle infinie? Dans cette boucle infinie, « Une exception uncaught élevée » est connecté à l'infini plusieurs fois:

- (void)reportException:(NSException *)anException
{
    // handle the exception properly
    (*NSGetUncaughtExceptionHandler())(anException);
}


0 commentaires

8
votes

Il s'avère être une solution très simple:

[[NSUserDefaults StandardDeFaultS] registerDefaults: @ {@ "Nsapplicationcrashononceptions": @yes}];

Il fait pas Crash votre application si vous utilisez @try ... @catch .

Je ne peux pas commencer à imaginer pourquoi ce n'est pas la valeur par défaut.


2 commentaires

Notez que cela ne frappe qu'après que Nsaplication ait fini d'appeler toutes ses méthodes de délégation.


En fait, c'est pire que ça. Cela ne fonctionne pas dans aucun code de manutention AppleEvent. Voir la réponse ci-dessous pour la solution de contournement.



1
votes

Il s'agit de la raison pour laquelle il apparaît que le gestionnaire d'exception n'appelle pas appelé vos méthodes de déléguée d'application est que _nsappleeventmanagergergenerglandLandler (une API privée) a un @try @catch bloc qui attrape toutes les exceptions et appelez simplement NSLog sur eux avant de retourner avec un erraeeventnothandled oserr. Cela signifie que non seulement vous allez manquer toutes les exceptions dans l'application Start Up, mais essentiellement des exceptions qui se produisent à l'intérieur de la manipulation d'un AppleEvent qui inclut (mais ne se limite pas à) les documents d'ouverture, l'impression, l'abandon et tout AppleScript.

Donc, mon "correction" pour cela: xxx

FUN EXTRA Remarque: nslog (@ "% @", exception) équivaut à NSLOG (@ "% @", exception.Reason) . NSLOG (@ "% @", [EXCEPTION DEBUGDEDESCRIPTION]) Vous donnera la raison plus la pile de pile entièrement symbolisée.

la version par défaut dans le _nsappleeventmanagergergenergénherkandler juste appelle nslog (@ "% @", exception) (MacOS 10.14.4 (18E226))


2 commentaires

Radar Filtré 50933952 - [NsappleeventManager] Veuillez effectuer une meilleure exploitation d'exception et RADAR 50933868 - NsappleeventManager doit respecter les paramètres de manutention des exceptions


Je devrais également noter que mon correctif ci-dessus modifiera la manière dont les Appleevents interagissent avec votre application, mais uniquement dans le cas où une exception est lancée. Sans le correctif, votre application reviendra une errappleEventNothandled et continuera à tenter de boiter, potentiellement dans un état corrompu. Avec mon correctif, l'application s'écrasera et que celui-ci a appelé que vous obtiendrez une erreur ConnectionInvalid.