2009-07-31 14 views
9

Quiero que mi aplicación nunca se cuelgue estúpidamente. Sé que la calidad del código es la solución raíz para esto. Pero aún necesito una aplicación que nunca se bloquee cuando ocurre algún error inesperado. Aquí está el código que quiero probar.Desarrollo de iPhone: cómo capturar Exception/NSError en Objective-C?

-(void)testException 
{ 
    @try 
    { 
     NSString* str; 
     [str release]; 
    } 
    @catch(NSException* ex) 
    { 
     NSLog(@"Bug captured"); 
    } 
} 

Sé que este no funciona. Porque release nunca genera una excepción. Aquí están mis preguntas:

  1. ¿Cómo se llega a este tipo de objetivo, se capturará el error, no se bloqueará?
  2. ¿Cómo puedo saber qué biblioteca del sistema generará una excepción y entonces puedo escribir un código y saber que funciona?

Esto es lo que he leído

  • a. Excepción Temas de programación para Cocoa
  • b. Manejo de errores de programación
    Guía para el cacao

Vengo de un fondo programador de Microsoft con experiencia en la que captura una excepción o una excepción inesperada siempre impiden que mi programa de estrellarse en un ambiente muy malo.

¿Cómo hicieron muchachos/chicas (programadores de Mac genio) para que los programas sin choques ocurrieran? Comparte tu experiencia.

Respuesta

3

Un problema que está teniendo es que str nunca se inicializa, lo que significa que str puede estar apuntando a cero (pero esto no está garantizado). Definitivamente está apuntando a la basura.

Si revisa su código, casi puedo garantizar que se llama a su versión en cero, que en Objective-C es completamente válido.

trate de hacer esto:

NSString *str = [[NSString alloc] initWithString:@"a string"]; 
[str release]; 
[str release]; 

Calling lanzamiento no desasignar un objeto, simplemente disminuye la cuenta de retención en 1. Cuando un recuento de objetos conservan es 0,

[self dealloc]; 

es llamado automáticamente .

Si el código anterior no arroja una excepción inmediatamente, puede ser porque el mensaje de desasignación real se retrasa en algún momento futuro (no estoy seguro exactamente cuando se llama a dealloc después de que el conteo de retención llega a 0. I pensar se llama inmediatamente y en el mismo hilo, pero algunos otros ninjas de Cocoa lo sabrán con certeza).

Lo que puede hacer es agregar una categoría a NSObject e implementar los métodos dealloc y release y tratar de atraparlo.

- (void)dealloc{ 

@try 
    { 
     [super dealloc]; 
    } 
@catch(NSException* ex) 
    { 
     NSLog(@"Bug captured"); 
    } 

} 



- (void)release{ 

    @try 
     { 
      [super release]; 
     } 
    @catch(NSException* ex) 
     { 
      NSLog(@"Bug captured"); 
     } 

    } 

La ventaja añadida es que este código será válido para todos los objetos de su aplicación, ya que es una categoría en NSObject.

Para estar completo, si solo practica las reglas de administración de memoria, estará bien.

+0

Gracias por la respuesta. Su respuesta me ayuda a comprender mejor el manejo de la memoria y ampliar mi conocimiento sobre el Objetivo C. Sin embargo, he intentado con el código, nunca se bloquean (Deben serlo, lo lanzo 4 veces, el recuento de referencias debería ser -3 si es posible). pero no se produjo ningún bloqueo en absoluto, tampoco se lanzó ninguna excepción. Sé que se bloqueará alguna vez. pero no se cuando. Entonces, de vuelta a lo básico, ¿hay alguna forma de evitar el bloqueo? –

+0

No se preocupe por retener los conteos. Nunca debes verificarlo, nunca es lo que crees que debería ser por varias razones. Debe encargarse de la administración de la memoria un método a la vez. Busque Stackoverflow y google para la gestión de la memoria de cacao. Hay muchos recursos para ayudarlo. Puede ser difícil de aprender al principio, pero se vuelve más automático. –

12

Objective-C es un tiempo de ejecución no administrado; el código que compila se ejecuta directamente en la CPU y no en una máquina virtual. Eso significa que no tiene la capa de supervisión que puede atrapar cada modo de falla posible de la manera en que lo hace cuando se ejecuta en .NET VM o JVM. En poco tiempo, la única manera de estar completamente seguro de que un programa no puede fallar es codificar cuidadosamente y probarlo a fondo. E incluso entonces, no estás seguro, solo piensas que lo eres.

La última versión de Xcode integra el analizador estático Clang ('Generar y Analizar' en el menú Compilar) que puede identificar algunas clases de posibles errores - estoy bastante seguro de que marcaría su ejemplo anterior, por ejemplo) . Pero no hay una bala mágica aquí; la única solución es el trabajo duro.

4

Prueba Prueba Prueba Prueba Prueba

Puede pasar todo el día escribiendo código de control de excepciones posibles excepciones (que en la práctica nunca ocurrirá), o puede crear conjuntos de pruebas exhaustivas y sólo escribir controladores de excepciones para situaciones que ocurren en la práctica.

Es por eso que casi nunca escribo manejadores de excepciones. Si arregla los problemas subyacentes que están causando la excepción, entonces no necesita manejar nada.

Por supuesto, hay situaciones en las que no se puede garantizar que una llamada a método no cause una excepción y debe estar preparado, pero definitivamente no es la solución envolver todo en @ try/@ catch blocks.

Cuestiones relacionadas