Domanda

Ho alcuni dubbi sulla gestione delle eccezioni in iPhone. Ecco loro:

  1. Supponiamo di avere una catena di metodi che vengono chiamati uno dopo l'altro, cioè il metodo del metodo B chiama B, che a sua volta chiama il metodo C, che chiama il metodo D. che è il posto migliore per mettere il mio blocco di cattura ( è il metodo A o B o C o D o tutti). Inoltre, devo visualizzare un avviso per l'utente che si è verificata un'eccezione e quindi, voglio registrare questa eccezione al mio server. Quindi, se sto scrivendo il mio try - cattura il blocco in tutti questi metodi e se si verifica un'eccezione nel metodo D; Quindi penso che l'avviso verrà visualizzato 4 volte e il servizio Web per la registrazione verrà anche chiamato 4 volte (fino a quando il controllo raggiungerà il blocco del metodo A). Quindi, dovrei usare @Throw; Nel blocco catch del metodo B, C e D e scrivere la mia logica nel blocco catch del metodo A (metodo di livello superiore) o dovrei evitare di scrivere - cattura nei metodi B, C e D.

  2. Ho bisogno di una sorta di codice di errore dall'eccezione (perché il mio servizio Web necessita di parametri e descrizione di errori). È possibile convertire un'eccezione all'errore o dovrò codificare duramente questo codice?

  3. Avevo letto da qualche parte su NssetuncaughtexceptionHandler. E penso che se riesco a impostare questo gestore (in AppDidFinishLaunching Metodo del delegato dell'app) e nel metodo del gestore, se mostro all'utente un avviso e chiamo il servizio Web; Quindi non ho bisogno di scrivere try - cattura il blocco in ciascuno dei miei metodi, in ciascuna delle mie classi. Ho ragione??

  4. Se si è verificata un'eccezione e ho scritto un tentativo - catch block o nssetuncaughtexceptionhandler, allora la mia app continuerà a funzionare o non risponderà a nessuno degli eventi utente. (Sono sicuro che gestirà l'incidente. Quello che voglio sapere è se appiccerà)

Qualcuno per favore illuminami su questo argomento di eccezione.

È stato utile?

Soluzione

0) Evita eccezioni nel cacao. Sono generalmente non rivelabili. Potresti catturarli per i tuoi errori, ma generalmente non è sicuro supporre che tu possa riprenderli.

1) Se devi catturarlo, prenderlo subito. Non scrivere i tuoi tiri - Invece, convertilo in qualcosa di simile a un NSError e passalo in giro. NSError può contenere tutte le informazioni necessarie per visualizzare o inviare un codice di errore e un messaggio localizzato.

2) Non puoi convertire un NSException in un NSError (direttamente) perché un NSException non ha tutte le proprietà NSError ha - è una rappresentazione di dati diversa. Per uno, non è disponibile un codice di errore. Due, la descrizione non è localizzata. Il meglio che puoi fare è creare un codice di errore e un dominio, quindi utilizzare le proprietà necessarie da NSException e conservalo in un NSError. Questo potrebbe sembrare qualcosa di simile al seguente:

// error checking omitted
extern NSString* const MONExceptionHandlerDomain;
extern const int MONNSExceptionEncounteredErrorCode;

NSError * NewNSErrorFromException(NSException * exc) {
    NSMutableDictionary * info = [NSMutableDictionary dictionary];
    [info setValue:exc.name forKey:@"MONExceptionName"];
    [info setValue:exc.reason forKey:@"MONExceptionReason"];
    [info setValue:exc.callStackReturnAddresses forKey:@"MONExceptionCallStackReturnAddresses"];
    [info setValue:exc.callStackSymbols forKey:@"MONExceptionCallStackSymbols"];
    [info setValue:exc.userInfo forKey:@"MONExceptionUserInfo"];

    return [[NSError alloc] initWithDomain:MONExceptionHandlerDomain code:MONNSExceptionEncounteredErrorCode userInfo:info];
}

@catch (NSException * exc) {
    NSError * err = NewNSErrorFromException(exc);
    ...
}

Se le API che usi le eccezioni di lancio che ci si aspetta che catturano e recuperano (ad es. Casi non veramente eccezionali), allora sì, potresti catturare e tentare di continuare. Sfortunatamente, chiunque scriva eccezioni sul cacao con l'intento che li catturerai probabilmente non capisce i problemi abbastanza bene da implementare una solida implementazione di distorsione (ad es. Anche se produce perdite, non è solido).

3) Non è davvero il tempo o il luogo per visualizzare un avviso. Se si installa un gestore di eccezioni di livello superiore (tramite NSSetUncaughtExceptionHandler) - Dovresti semplicemente registrare un messaggio - quindi il gestore delle eccezioni interromperà. La tua app è in uno stato instabile: continuare è peggio che abortire. Potresti voler inviare questi messaggi personalizzati a casa, è meglio farlo al prossimo lancio della tua app.

4) Nella maggior parte dei casi, l'app è in uno stato instabile e non dovresti continuare. Ma, per rispondere effettivamente per quei casi d'angolo: "Sì, puoi recuperare e continuare quando prendi, ma dovresti solo tentare di recuperare e continuare quando l'API di lancio afferma che il recupero è supportato. Se il problema è al di fuori del tuo controllo, E il problema non è eccezionale (ad esempio il file non trovato) e il venditore si aspetta davvero che continui, allora dovrei presumere che si aspettano che tu continui, anche se in realtà non è (al 100% sicuro). ". Non tentare di recuperare/continuare dal gestore delle eccezioni di alto livello (il programma interromperà dopo il ritorno). Se vuoi essere molto elegante e presente che immediatamente su OSX, un altro processo sarebbe il migliore. Se stai chiamando una pura interfaccia C ++, allora la svolta è ben definita e è necessaria la necessità di catturare: continuare se è recuperabile. Le eccezioni in C ++ possono essere recuperabili e ben definite: sono anche utilizzate in modo abbastanza ampiamente (comprese condizioni meno che eccezionali).

(IMO ...) Le eccezioni in OBJC non avrebbero dovuto essere introdotte e qualsiasi metodo che lancia dal sistema o dalle librerie di terze parti dovrebbe essere deprecato. Non si rilassano bene o in modo ben definito. Inoltre, i flussi di svolgimento contro il normale flusso del programma di cacao. Ciò significa che toccare la memoria/le relazioni di qualsiasi oggetto OBJC che era in mutazione al momento del tiro e che si trova tra il tiro e la cattura è buono come un comportamento indefinito. Il problema è: non hai idea di cosa sia quella memoria (nella maggior parte dei casi e entro un tempo di manutenzione ragionevole). Le eccezioni di C ++ sono ben definite e si rilassano correttamente (ad esempio i distruttori sono chiamati) - ma cercare di continuare in un contesto OBJC sta ignorando qualsiasi conseguenza di comportamenti indefiniti. IMO, dovrebbero esistere solo per OBJC ++ (perché C ++ li richiede).

In un mondo ideale, i tuoi programmi OBJC e le biblioteche che usi non utilizzerebbero le eccezioni (affatto). Dato che usi librerie che lanciano (incluso il cacao), installa un gestore di eccezioni di alto livello Solo se hai bisogno di alcune informazioni speciali sull'errore. Dove l'API impone che tu possa aspettarti un'eccezione lanciata a causa di circostanze al di fuori del tuo controllo e dovresti recuperare, quindi scrivi una cattura ma converti immediatamente quella logica in normale flusso del programma (ad es. NSError) - Non devi mai scrivere il tuo tiro. -[NSArray objectAtIndex: e "l'oggetto non risponde al selettore" sono esempi di errori del programmatore: dovrebbero non essere catturato, ma il programma dovrebbe essere corretto.

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