48 votos

Objective-C Excepciones

Acabo de terminar una aplicación para el iPhone curso de programación. Como parte del curso, vi

  • Objective-C proporciona el manejo de excepciones el uso de la @try directiva
  • El sistema de la biblioteca no utilizar el manejo de excepciones, prefiriendo return nil

Me pregunté si debería utilizar el manejo de excepciones para el nuevo código escribí (por ejemplo, si escribo tanto en el front-end y el código de lógica, por lo que la comunicación entre ellos está en mis manos), pero me dijeron que no, uno no debe usar excepciones para el nuevo código. (Pero falló a la hora de elaborar, a continuación, la clase pasó, pensé que tal vez la razón se manifestaría más tarde..)

Seguramente excepciones son superiores a return nil? Usted puede contraer determinados tipos, no tener la tentación de ignorar ignorar el tipo de retorno de una función que normalmente tiene éxito, usted tiene mensajes de texto que pueden ser registrados, que permiten a su código para centrarse en el caso normal y por lo tanto ser más legible. ¿Por qué utilizar excepciones.

Entonces, ¿qué te parece? Fue mi entrenador el derecho a no usar Objective-C las excepciones? Si es así, ¿por qué?

58voto

zneak Puntos 45458

Es peligroso para lanzar excepciones en circunstancias donde los recursos no son gestionadas automáticamente. Este es el caso de el marco de Cacao (y vecino de marcos), ya que utilizan el manual de referencia de contar.

Si usted lanza una excepción, cualquier release llamar saltar al desenrollar la pila va a resultar en una fuga. Esto debe limitar tothrowing sólo si estás seguro de que no vas a recuperar ya que todos los recursos son devueltos al sistema operativo cuando un proceso se cierra.

Por desgracia, NSRunLoops tienden a capturar todas las excepciones que se propagan a ellos, así que si te tiro durante un evento, te curriculum vitae a la siguiente evento. Esto es, obviamente, muy mal. Por lo tanto, es mejor que simplemente no la tire.

Este problema se ve disminuida si utiliza recolección de basura Objective-C, como cualquier recurso representado por un Objetivo-C objeto será debidamente publicado. Sin embargo, el C de los recursos (tales como descriptores de archivo o malloc-memoria asignada) que no están envueltos en un Objetivo-C objeto todavía de fugas.

Así que, con todo, no la tire.

El Cacao de la API tiene varias soluciones para esto, como usted ha mencionado. Volviendo nil y NSError** patrón son dos de ellos.

Aclaraciones para el ARCO

ARCO de los usuarios puede elegir habilitar o deshabilitar completo excepción de seguridad. Cuando la excepción de seguridad está habilitada, el ARCO generará código para liberar fuertes referencias a la hora de su ámbito de aplicación es asesinado, por lo que es seguro para el uso de excepción en el código. ARCO no revisión de librerías externas para permitir a excepción apoyo en ellos, así que usted debe tener cuidado de donde tirar (y especialmente cuando se captura), aunque con la excepción de soporte habilitado en su programa.

ARCO excepción de soporte puede ser activado con -fobjc-arc-exceptions o discapacitadas -fno-objc-arc-exceptions. Por defecto, está desactivado en Objective-C, pero habilitado en Objective-C++.

Completo excepción de seguridad en Objective-C está desactivada por defecto porque el Ruido autores asumen que Objective-C programas de no recuperarse de una excepción de todos modos, y debido a que hay un gran tamaño del código de costes y una pequeña penalización de rendimiento asociados a la limpieza. En Objective-C++, por otro lado, C++ ya que introduce una gran cantidad de código de limpieza, y la gente es mucho más probable que en realidad necesita la excepción de seguridad.

Esto es todo desde el ARCO de la especificación sobre la LLVM sitio web.

30voto

bbum Puntos 124887

En el Cacao y iOS programador, las excepciones se utiliza para indicar que no recuperable error del programador. Cuando se produce una excepción por los marcos de referencia, se indica que los sistemas han detectado un estado de error que es no recuperable y para que el estado interno es ahora indefinido.

Así, las excepciones lanzadas a través de un marco de código de salir de los marcos de referencia en un estado indefinido. I. e. usted no puede hacer algo como:

void a() {
    @throw [MyException exceptionWithName: @"OhNoes!"  ....];
}

@try {
    ... call into framework code that calls a() above ...
} @catch (MyException e) {
    ... handle e ...
}

Línea de base:

Las excepciones no son para ser utilizado en el Cacao para el control de flujo, validación de entrada de usuario, la validez de los datos de detección o de lo contrario indicar errores recuperables. Para eso, el uso de la NSError** el patrón como se documenta aquí (gracias Abizem).

(Tenga en cuenta que hay un pequeño número de API que no violen esta -- cuando una excepción se utiliza para indicar un estado recuperable. Errores han sido presentadas en contra de estos que van a dejar de usar y, finalmente, eliminar las inconsistencias.)


Finalmente consideró que el documento que estaba buscando:

Importante: Usted debe reservar el uso de las excepciones para la programación o inesperado errores de tiempo de ejecución, tales como fuera de los límites de acceso a las colecciones, los intentos para mutar objetos inmutables, el envío de un mensaje no válido, y la pérdida de la conexión con el servidor de ventanas. Por lo general toma el cuidado de este tipo de errores con excepciones cuando un la aplicación está siendo creado en lugar que en tiempo de ejecución.

Si usted tiene un cuerpo de código (como la librería de terceros) que utiliza las excepciones para manejar el error condiciones, usted puede utilizar el código tal y como está en su Cacao de la aplicación. Pero debe asegurarse de que cualquier espera excepciones en tiempo de ejecución no escapan de estos subsistemas y terminan en el código del llamador. Por ejemplo, un análisis de la biblioteca puede utilizar excepciones internamente para indicar la existencia de problemas y permitir una salida rápida a partir de un análisis de estado que podría ser profundamente recursiva; sin embargo, usted debe tener cuidado para coger tales excepciones en el nivel superior de la biblioteca y las traducen en un código de retorno adecuado o el estado.

7voto

Abizern Puntos 52378

Creo, y otros que se me corrija si me equivoco, que las Excepciones deben ser utilizados para la captura de programador de errores, mientras que el NSError error de tipo de manejo debe ser utilizado para condiciones excepcionales que se producen durante la ejecución del programa.

Y como para regresar nil, que no todas las funciones que puede tener problemas no devuelven un nil, que también puede (y debe) proporcionar más información usando el NSError objeto que se pasa como parámetro.

Ver también

3voto

JeremyP Puntos 46808

Personalmente, no veo ninguna razón para no usar excepciones en su propio código. El patrón de excepción, es más limpia para el manejo de errores de

  • tener siempre un valor de retorno,
  • asegurándose de que uno de los posibles valores de retorno que realmente significa el "error"
  • pasando un parámetro adicional que es una referencia a un NSError*
  • rociar el código con el código de limpieza para cada error de retorno o explícito gotos para saltar a un error comunes sección de limpieza.

Sin embargo, es necesario tener en cuenta que otras personas de código no está garantizada para manejar la excepción correctamente (si es puro C, en el hecho de que no puede manejar excepciones correctamente). Por lo tanto, usted debe nunca permitir una excepción a propagarse más allá de los límites de su código. Por ejemplo, si usted lanza una excepción en las entrañas de un método de delegado, debe controlar que la excepción, antes de regresar al remitente de que el delegado del mensaje.

1voto

Evan Mulawski Puntos 28536

El tipo de gestión de errores a utilizar depende de lo que usted está tratando de lograr. Casi todos los de Apple métodos se rellenan un NSError objeto que se puede acceder a error.

Este tipo de gestión de errores puede ser usado en conjunción con un bloque try-catch dentro de una sección de código:

-(NSDictionary *)getDictionaryWithID:(NSInteger)dictionaryID error:(NSError **)error
{
    @try
    {
         //attempt to retrieve the dictionary
    }
    @catch (NSException *e)
    {
        //something went wrong
        //populate the NSError object so it can be accessed
    }
}

En pocas palabras, el objetivo del método determina el tipo de manejo de errores que usted debe usar. Pero, en el ejemplo anterior, usted puede utilizar ambos.

Un uso común para el bloque try-catch:

@try
{
    [dictionary setObject:aNullObject forKey:@"Key"];
}
@catch (NSException *e)
{
    //one of the objects/keys was NULL
    //this could indicate that there was a problem with the data source
}

Espero que esto ayude.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X