2011-02-15 18 views
78

En Cocoa, ¿cuándo debería usar NSAssert, NSException, NSError?Objective-C: Assertion vs. Exception vs. Error

Aquí es lo que he estado pensando:

NSAssert - Al crear un programa cliente que se utiliza para el propio beneficio programadores de dobles reglas de verificación, convenciones, suposiciones o pre-condiciones y post-condiciones?

NSException - Al crear una biblioteca de terceros para el beneficio de otros programadores que utilizan la biblioteca, para que sepan de inmediato cuando una entrada no es válida?

NSError - Cuando la interfaz con un sistema externo para obtener datos como un archivo, base de datos o servicio web que no está garantizado que me diera un resultado?

Respuesta

98

Un NSAssert lanzará una excepción cuando falle. Así que NSAssert es una forma breve y fácil de escribir y verificar cualquier suposición que hayas hecho en tu código. No es (en mi opinión) una alternativa a las excepciones, solo un atajo. Si una afirmación falla, algo ha ido terriblemente mal en su código y el programa no debería continuar.

Una cosa a tener en cuenta es que NSAssert no se compilará en su código en una compilación de lanzamiento, por lo que normalmente se usa para verificar la cordura durante el desarrollo. En realidad, tiendo a usar una macro de afirmación personalizada que siempre está activa.

Los tiempos que le @throw su propio NSException son cuando usted quiere definitivamente en una versión de lanzamiento, y en cosas como las bibliotecas públicas/interfaz cuando algunos argumentos no son válidos o que han sido llamados de forma incorrecta. Tenga en cuenta que no es una práctica estándar en @catch una excepción y continúa ejecutando su aplicación. Si prueba esto con algunas de las bibliotecas estándar de Apple (por ejemplo, Core Data), pueden suceder cosas malas.De manera similar a una afirmación, si se lanza una excepción, la aplicación generalmente debe terminar bastante rápido porque significa que hay un error de programación en alguna parte.

NSErrors se deben utilizar en sus bibliotecas/interfaces para errores que no son errores de programación, y que pueden recuperarse. Puede proporcionar códigos de información/error a la persona que llama y ellos pueden manejar el error limpiamente, alertar al usuario si corresponde y continuar la ejecución. Esto normalmente sería para cosas como un error de archivo no encontrado o algún otro error no fatal.

+14

Para expresarlo con más fuerza, una ** NSException ** no se debe usar para indicar un error recuperable. – bbum

+25

En otras palabras: Obj-C's NSException == Clase de error de Java, y Obj-C's NSError == Clase de excepción de Java. ¡Hurra por consistencia en términos! – Tustin2121

+2

En realidad, NSAssert se compilará en su código si no agrega NS_BLOCK_ASSERTIONS en sus archivos de prefijos precompilados. Lea la [respuesta] (http://stackoverflow.com/a/25660769/1764735) a continuación (solo obtenga 50 para recomendar ahora :) – likid1412

1

En general, las excepciones se utilizan para señalar los errores del programador: son cosas que no deberían suceder. Los errores se utilizan para indicar las condiciones de error que pueden surgir en el funcionamiento normal del programa: errores de usuario, básicamente, o condiciones externas que deben ser ciertas pero que pueden no serlo. Por lo tanto, tratar de eliminar algún elemento bloqueado en un documento puede ser un error, y tratar de descargar un archivo sin una conexión a Internet sería un error, pero tratar de acceder a un elemento no válido en una colección sería una excepción.

Las aserciones se utilizan generalmente en las pruebas, y AFAIK no se utilizan como un mecanismo general de manejo de errores como los demás.

+0

Las afirmaciones se pueden usar para forzar invariantes. Por ejemplo, 'NSParameterAssert (someParam! = Nil);' aplicará el invariante de que el parámetro especificado no debe ser nil. –

+0

@Kevin Ballard: Las aserciones normalmente se definen a partir de compilaciones de versiones, o al menos fueron las últimas que verifiqué, así que como dije, no son un mecanismo general de manejo de errores. – Chuck

+1

Pueden serlo, pero no se omiten por defecto. Tienes que cambiar una configuración de compilación para obtener ese comportamiento. –

3

La convención en Cocoa es que una excepción indica un error del programador. Una gran cantidad de código, incluido el código de marco, no está diseñado para funcionar correctamente después de lanzar una excepción.

Cualquier tipo de error que debería ser recuperable está representado por un NSError. También hay un sistema para presentar NSError s al usuario. Como dices, esto es principalmente útil para recursos externos falibles.

Conceptualmente, una aserción es una afirmación de que un predicado determinado siempre se evalúa como verdadero; si no lo hace, el programa está roto. Si bien su comportamiento se puede modificar, la familia NSAssert es, por defecto, una forma conveniente de arrojar NSInternalInconsistencyException s (con la opción de desactivarlos en versiones de lanzamiento).

2

Editar: En Xcode 4.2, assertions are turned off by default for release builds,

Ahora NSAssert no serán compilados en su código en un comunicado de construir, pero puede cambiarlo en configuración de generación


@ Mike Weller , Hay uno mal en tu respuesta.

Una cosa a destacar es que NSAssert no se compila en el código en una versión de lanzamiento, por lo que este se utiliza normalmente para el control de la cordura durante el desarrollo.

En realidad, NSAssert se compila en el código si no se agrega NS_BLOCK_ASSERTIONS en sus archivos prefijo precompilados.

En Nota TN2190 Técnica podemos encontrar:

macros como NDEBUG para apagar afirman C o NS_BLOCK_ASSERTIONS para apagar NSAssert de la Fundación son importantes para especificar para los archivos de prefijo precompilados

O puede leer este: How to know if NSAssert is disabled in release builds?

Cuestiones relacionadas