Domanda

Uno dei miei amici mi ha chiesto di non usare NSException in iPhone Apps. La ragione per cui ha dato è stata "collo di bottiglia". Ma io non sono convinto di esso.

Qualcuno mi può confermare che dovremmo trattenere usare NSException in iPhone App? Se si dispone di migliori pratiche per l'utilizzo NSException, si prega di fornire anche questo.

UPDATE:

Questo link noi richieste per utilizzare la gestione delle eccezioni a livello di applicazione. Avere qualcuno mai fatto? Si prega di fornire i vantaggi di esso e qualsiasi altra prestazione intoppi si potrebbe creare.

È stato utile?

Soluzione

In breve:

Non utilizzare le eccezioni per indicare gli errori tutt'altro che irreversibile

È opportuno solo per uso @ provare / @ fermo a che fare con errori irreversibili. Non è mai opportuno utilizzare @ gettare / @ try / catch per @ fare il controllo del flusso di operazioni analoghe su iOS o Mac OS X. Anche allora, considerare attentamente se si sta meglio con un'eccezione per indicare un errore irreversibile o semplicemente crash ( chiamare abort ()); Un incidente spesso lascia dietro significativamente più prove.

Per esempio, non sarebbe opportuno utilizzare per la cattura di out-of-bounds eccezioni a meno che il vostro obiettivo è quello di catturare loro e in qualche modo segnalare l'errore, poi - in genere - incidente o, per lo meno, avvertire l'utente che la vostra applicazione è in uno stato incoerente e può perdere i dati.

comportamento di qualsiasi eccezione generata attraverso il codice del framework del sistema non è definito.


  

Può spiegare il "comportamento di qualsiasi   eccezione generata attraverso il sistema   codice del framework è indefinito." in   dettaglio?

Certo.

I quadri di sistema usano un design in cui ogni eccezione è considerato un fatale, non recuperabile, l'errore; un errore di programmazione, per tutti gli effetti. Ci sono un numero molto limitato di eccezioni (eh) a questa regola.

In questo modo, nella loro attuazione, i quadri sistema non garantire che tutto è necessariamente correttamente ripulito se un'eccezione viene lanciata che passa attraverso codice del framework del sistema. Sine l'eccezione è, per definizione, non recuperabile, perché pagare il costo della pulizia?

Considerate questo stack di chiamate:

your-code-1()
    system-code()
        your-code-2()

vale a dire. codice in cui le chiamate codice in codice sistema che chiama in più del codice (un modello molto comune, anche se gli stack di chiamate sono ovviamente molto più profonda).

Se your-code-2 genera un'eccezione, che le eccezioni passa sopra system-code significa che il comportamento è indefinito; system-code può o non può lasciare l'applicazione in una non definita, potenzialmente crashy o dati-perdita, dello stato.

In alternativa, con più forza. Non è possibile generare un'eccezione nel your-code-2 con l'aspettativa che si può prendere e gestire in your-code-1

Altri suggerimenti

Non ho la gestione delle eccezioni usato per il mio abbastanza intensiva audio app senza alcun problema. Dopo molto la lettura e un po 'di benchmarking e analisi di smontaggio, ho giunto alla conclusione controverso che non c'è una vera ragione per non loro (in modo intelligente) e un sacco di usare la ragione per non (NSError puntatore punti, infinite condizionali ... che schifo!). La maggior parte di ciò che si dice sui forum è solo ripetendo l'Apple Docs.

vado in un po 'di dettagli in questo post del blog ma sarò delineare i miei risultati qui:

Mito 1: @ try / @ catch / @, infine, è troppo costoso (in termini di CPU)

Sul mio iPhone 4, lancio e la cattura 1 milione di eccezioni impiega circa 8,5 secondi. Ciò equivale a circa solo 8,5 microsecondi per ciascuno. Costoso in tempo reale filo CoreAudio? Forse un po '(ma si era mai buttare eccezioni ci faresti ??), ma un 8.5µs ritardo nella UIAlert dicendo che l'utente si è verificato un problema di apertura proprio file, sta andando per essere notato?

Mito 2: @try blocchi hanno un costo sulla 32bit iOS

La documentazione di Apple parlano di "blocchi a costo zero @try su 64bit " e lo stato che 32 bit comporta un costo. Un po comparativa e smontaggio analisi sembra indicare che esiste blocchi @try costo zero su iOS 32bit (processore ARM) pure. Apple ha fatto vuol dire 32bit Intel

Mito 3: Importa che eccezioni generate Attraverso cacao quadri sono indefiniti

Sì, sono "undefined", ma quello che stai facendo gettando attraverso il framework di Apple in ogni caso? Naturalmente Apple non li gestire per voi. Il punto di attuare la gestione delle eccezioni per errori recuperabile è quello di gestire localmente -. Solo che non tutti i-single-line "localmente"

Un caso limite è qui con metodi come NSObject:performSelectorOnMainThread:waitUntilDone:. Se il parametro in seguito è SI, questo agisce come una funzione sincrona, nel qual caso si potrebbe essere perdonato per aspettandosi l'eccezione a bollire fino a vostra portata di chiamata. Ad esempio:

/////////////////////////////////////////////////////////////////////////
#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;
}
// ...

In questo caso l'eccezione passerebbe "attraverso il quadro di cacao" (anello run del thread principale) manca il pescato e schiantarsi. Si può facilmente ovviare a questo utilizzando dispatch_synch di GCD e mettendo in esso del blocco la tesi della chiamata al metodo più l'eventuale gestione delle eccezioni.

Perché utilizzare NSException finita NSError di

Chiunque abbia mai fatto il lavoro in una delle strutture più vecchie C-based come Core Audio sa cosa sia un lavoro di routine si sta controllando, la manipolazione e la segnalazione di errori. Il vantaggio principale @ try / catch and @ NSExceptions fornisce è quello di rendere il più pulito il codice e più facile da mantenere.

Diciamo che avete 5 righe di codice che opera su un file. Ognuno potrebbe gettare uno di, diciamo, 3 diversi errori (ad esempio, lo spazio su disco, errore di lettura, ecc). Invece di avvolgere ogni linea in una condizione che i controlli per un valore di ritorno NO e poi affida il puntatore indagini NSError a un altro metodo objC (o peggio, utilizza una macro #define!), Si avvolge tutte e 5 le linee in un singolo @try e gestire ogni errore proprio lì. Pensate delle linee che si risparmia!

Con la creazione di sottoclassi NSException, si può facilmente messaggi di errore anche centralizzare e evitare di avere il vostro codice disseminato di loro. Si può anche facilmente distinguere eccezioni del app "non letali" da errori fatali programmatore (come NSAssert). È anche possibile evitare la necessità per la costante "nome" (il nome del sottoclasse, è il "nome").

Gli esempi di tutto questo e maggiori dettagli sui parametri di riferimento e smontaggio sono su questo post del blog ...

Le eccezioni più try / catch / finally èil paradigma usato da praticamente ogni altra lingua maggiore (C ++, Java, PHP, Ruby, Python). Forse è ora di cadere la paranoia e abbracciare come bene ... almeno in iOS.

In generale chiedetevi se si sta cercando di segnalare un errore, o si fa realmente avere una condizione eccezionale? Nel primo caso, allora è una pessima idea, indipendentemente da qualsiasi problema di prestazioni, reale o percepita. In quest'ultimo caso, è sicuramente la cosa giusta da fare.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top