Pregunta

Tengo algunas dudas con respecto al manejo de excepciones en iPhone. Aquí están ellos:

  1. Supongamos que tengo una cadena de métodos que se llaman uno tras otro, es decir, el método A llama Método B, que a su vez llama al Método C, que llama al Método D. que es el mejor lugar para poner mi bloque de intento-Catch ( ¿Es el método a o b o c o d o todos ellos)? Además, necesito mostrar una alerta al usuario de que se ha producido una excepción y luego, quiero registrar esta excepción a mi servidor. Entonces, si estoy escribiendo mi try - Catch Bloque en todos estos métodos y si se produce una excepción en el Método D; Luego, creo que la alerta se mostrará 4 veces y el servicio web para el registro también se llamará 4 veces (hasta que el control alcance el bloque del método a). Entonces, debería usar @throw; En el bloque de captura del método B, C y D y escriba mi lógica en el bloque de captura del método A (método de nivel superior) o debo evitar escribir intento, atrapar en absoluto en los métodos B, C y D.

  2. Necesito algún tipo de código de error de la excepción (porque mi servicio web necesita parámetros código de error y descripción). ¿Es posible convertir una excepción al error o necesitaré codificar este código?

  3. Había leído en alguna parte sobre nssetunceughtexceptionhandler. Y creo que, si puedo configurar este controlador (en AppDidFinishLaunching Method of App Delegate) y en el método del controlador, si muestro al usuario alguna alerta y llamo al servicio web; Entonces no necesito escribir try - atrapar el bloque en cada uno de mis métodos, en cada una de mis clases. ¿Estoy en lo cierto?

  4. Si se ha producido una excepción y he escrito un BLOCK TRY - Catch o NSSetUncoughedExceptionHandler, entonces mi aplicación continuará ejecutándose o no responderá a ninguno de los eventos de usuario. (Estoy seguro de que manejará el choque. Lo que quiero saber es si colgará)

Alguien por favor ilumíname sobre este tema de excepción.

¿Fue útil?

Solución

0) Evite las excepciones en el cacao. Generalmente no son recuperables. Puede atraparlos para obtener su propio informe de error, pero generalmente es inseguro asumir que puede recuperarse de ellos.

1) Si necesita atrapar, atraparlo inmediatamente. No escribas tus propios lanzamientos - En cambio, conviértalo en algo como un NSError y pasar eso. NSError Puede contener toda la información que necesita para mostrar o enviar un código de error, así como un mensaje localizado.

2) No puedes convertir un NSException en una NSError (directamente) Porque un NSException no tiene todas las propiedades un NSError ha: es una representación de datos diferente. Por un lado, no hay un código de error disponible. Dos, la descripción no está localizada. Lo mejor que puede hacer es crear un código de error y un dominio, luego usar las propiedades que necesita de la NSException y guarda eso en un NSError. Esto podría parecerse a lo siguiente:

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

Si las API que utiliza excepciones de lanzamiento de las que se espera que atrape y se recupere (por ejemplo, casos no excepcionales), entonces sí, podría atrapar e intentar continuar. Desafortunadamente, cualquiera que escriba excepciones en el cacao con la intención de que los atrape probablemente no comprenda los problemas lo suficientemente bien como para implementar una implementación de relajación sólida (por ejemplo, incluso si produce fugas, no es sólida).

3) Ese no es realmente el momento o el lugar para mostrar una alerta. Si instala un manejador de excepciones de nivel superior (a través de NSSetUncaughtExceptionHandler) - Simplemente debe registrar un mensaje - entonces el controlador de excepción abortará. Su aplicación está en un estado inestable: continuar es peor que abortar. Es posible que desee enviar estos mensajes personalizados a casa, es mejor hacerlo en el próximo lanzamiento de su aplicación.

4) En la mayoría de los casos, su aplicación está en un estado inestable y no debe continuar. Pero, para responderlo realmente por esos casos de esquina: "Sí, puede recuperarse y continuar cuando se atrapa, pero solo debe intentar recuperarse y continuar cuando la API de lanzamiento establece que la recuperación es compatible. Si el problema está más allá de su control, Y el problema no es excepcional (por ejemplo, un archivo no encontrado), y el proveedor realmente espera que continúe, entonces tendría que asumir que espera que continúe, aunque realmente no sea (100% seguro) ". No intente recuperarse/continuar dentro de su controlador de excepciones de nivel superior (el programa abortará después de que regrese). Si desea ser muy elegante y presentarlo inmediatamente en OSX, otro proceso sería el mejor. Si está llamando a través de una interfaz C ++ pura, entonces el relajado está bien definido y la necesidad de atrapar es necesaria: continúe si es recuperable. Las excepciones en C ++ pueden ser recuperables y bien definidas: también se usan bastante ampliamente (incluidas condiciones menos que excepcionales).

(OMI ...) No deberían haberse introducido excepciones en OBJC, y cualquier método que arroje de bibliotecas del sistema o de terceros debe estar en desuso. No se relajan bien ni de una manera bien definida. Además, el relajación fluye contra el flujo normal del programa de cacao. Eso significa que tocar la memoria/relaciones de cualquier objeto objc que estaba en mutación en el momento del lanzamiento y que se encuentra entre el lanzamiento y la captura es tan bueno como el comportamiento indefinido. El problema es que no tiene idea de qué es esa memoria (en la mayoría de los casos y en un tiempo de mantenimiento razonable). Las excepciones de C ++ están bien definidas, y se relajan correctamente (por ejemplo, los destructores se llaman), pero tratar de continuar en un contexto OBJC es ignorar las consecuencias del comportamiento indefinido. En mi opinión, solo deberían existir para OBJC ++ (porque C ++ los requiere).

En un mundo ideal, sus programas OBJC y las bibliotecas que usa no usarían excepciones (en absoluto). Dado que usa bibliotecas que lanzan (incluido el cacao), instale un controlador de excepción de nivel superior Solo si necesita información especial sobre el error. Donde la API exige que pueda esperar una excepción lanzada Debido a circunstancias más allá de su control y se espera que se recupere, luego escriba una captura pero convierta inmediatamente esa lógica al flujo normal del programa (por ejemplo, NSError) - Nunca necesitas escribir tu propio lanzamiento. -[NSArray objectAtIndex: y "objeto no responde al selector" son ejemplos de errores de programador: deberían no ser atrapado, pero el programa debe corregirse.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top