J'ai utilisé la gestion des exceptions pour mon audio app assez intensif sans aucun problème. Après beaucoup de lecture et un peu d'analyse comparative et de désassemblage, j'en suis arrivé à la conclusion controversée qu'il n'y a pas de raison de ne pas les utiliser (intelligemment) et beaucoup de raisons de ne pas les utiliser (pointeurs NSError ... beurk!). La plupart de ce que les gens disent sur les forums ne fait que répéter les Apple Docs.
je vais dans un peu de détails dans this blog post mais je vais décrire mes résultats ici:
Mythe 1: @ essayer/@ catch/@ est finalement trop cher (en termes de CPU)
Sur mon iPhone 4, lancer et attraper 1 million d'exceptions prend environ 8,5 secondes. Cela équivaut à environ seulement 8,5 microsecondes pour chacun. Cher dans votre thread CoreAudio en temps réel? Peut-être un peu (mais vous ne jetteriez jamais d'exceptions là-bas ??), mais un retard de 8.5μs dans l'UIAlert indiquant à l'utilisateur qu'il y avait un problème à ouvrir son fichier, cela va-t-il être remarqué?
Mythe 2: Les blocs de @try un coût sur iOS 32bit
Les documents d'Apple parlent de « blocs de @try à coût zéro sur 64bit » et que l'état 32 bits entraîne un coût. Une petite analyse de benchmarking et de désassemblage semble indiquer qu'il existe également des blocs @try à coût nul sur iOS 32 bits (processeur ARM). Apple a-t-il voulu dire 32 bits Intel?
Mythe n ° 3: Il importe que des exceptions Jeté à travers des cadres de cacao sont Undefined
Oui, ils sont « non défini », mais que faites-vous jeter dans le cadre d'Apple de toute façon? Bien sûr Apple ne les gère pas pour vous. L'objectif de la gestion des exceptions pour les erreurs récupérables est de les gérer localement, mais pas toutes les lignes "localement".
Un cas de bord est ici avec des méthodes comme NSObject:performSelectorOnMainThread:waitUntilDone:
. Si le paramètre suivant est YES, cela agit comme une fonction synchrone, auquel cas vous pourriez être pardonné d'attendre que l'exception atteigne la portée de votre appel. Par exemple:
/////////////////////////////////////////////////////////////////////////
#pragma mark - l5CCThread
/////////////////////////////////////////////////////////////////////////
@interface l5CCThread : NSThread @end
@implementation l5CCThread
- (void)main
{
@try {
[self performSelectorOnMainThread:@selector(_throwsAnException) withObject:nil waitUntilDone:YES];
} @catch (NSException *e) {
NSLog(@"Exception caught!");
}
}
- (void)_throwsAnException { @throw [NSException exceptionWithName:@"Exception" reason:@"" userInfo:nil]; }
@end
/////////////////////////////////////////////////////////////////////////
#pragma mark - l5CCAppDelegate
/////////////////////////////////////////////////////////////////////////
@implementation l5CCAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
l5CCThread *thd = [[l5CCThread alloc] init];
[thd start];
return YES;
}
// ...
Dans ce cas, l'exception passerait « dans le cadre de cacao » (la boucle d'exécution du thread principal) manquant vos prises et s'écraser. Vous pouvez facilement contourner cela en utilisant dispatch_synch
de GCD et en mettant dans son argument de bloc l'appel de méthode plus n'importe quelle gestion d'exception.
Pourquoi utiliser NSException de plus de
NSError
de Quiconque a déjà fait un travail dans l'un des cadres basés C-anciens comme Core Audio sait ce qu'est une corvée, il vérifie, la manipulation et les erreurs de déclaration. Le principal avantage de @ try/@ catch et NSExceptions est de rendre votre code plus propre et plus facile à maintenir.
Disons que vous avez 5 lignes de code qui fonctionnent sur un fichier. Chacun d'entre eux peut, par exemple, lancer 3 erreurs différentes (par exemple, sur l'espace disque, erreur de lecture, etc.). Au lieu d'encapsuler chaque ligne dans un conditionnel qui vérifie une valeur de retour NO et externalise l'investigation du pointeur NSError vers une autre méthode ObjC (ou pire, utilise une macro #define
!), Vous enroulez toutes les lignes un seul @try et gérer chaque erreur là-bas. Pensez aux lignes que vous économiserez! En créant des sous-classes NSException, vous pouvez également centraliser facilement les messages d'erreur et éviter que votre code ne soit jonché de détritus. Vous pouvez également distinguer facilement les exceptions «non fatales» de votre application des erreurs programmatiques fatales (comme NSAssert). Vous pouvez également éviter la nécessité de la constante "nom" (le nom de la sous-classe, est le "nom").
Des exemples de tout cela et plus de détails sur les points de référence et le démontage sont on this blog post ...
Exceptions, plus try/catch/est finalement le paradigme utilisé par à peu près toutes les autres langues principales (C++, Java, PHP, Ruby, Python). Peut-être qu'il est temps de laisser tomber la paranoïa et de l'adopter aussi ... au moins dans iOS.
Pouvez-vous expliquer le "Comportement de toute exception levée par le biais du code de structure du système est indéfini." en détail? – Krishnan
Mis à jour la question .... – Krishnan
+1, il est gentil one.Peut-on me dire s'il vous plaît mon hypothèse concernant l'exception n'est pas correct.Si j'utilise NSException en cas d'exception particulière (supposons Array hors de la limite) .then charge toutes les classes pour vérifier l'exception. Veuillez répondre. – Ishu