2011-01-17 6 views
5

me cogió la costumbre de codificación de mi tratamiento de errores de esta manera:NSError: ¿Usar nil para detectar el error en realidad desactiva el informe de errores?

NSError* error = nil; 
NSDictionary *attribs = [[NSFileManager defaultManager] removeItemAtPath:fullPath error:&error]; 
if (error != nil) { 
    DLogErr(@"Unable to remove file: error %@, %@", error, [error userInfo]); 
    return; 
} 

Pero al mirar a la documentación Parece como si tuviera este mal .:

- (BOOL)removeItemAtPath:(NSString *)path error:(NSError **)error 

If an error occurs, upon return contains an NSError object that describes the problem. Pass NULL if you do not want error information.

técnicamente no hay diferencia entre nulo y NULL, ¿significa esto que estoy apagando esto y nunca recibiré un mensaje de error (incluso si la eliminación en el ejemplo anterior falló)? ¿Hay alguna forma mejor de codificar esto?

Gracias.

+1

hay una diferencia entre las negativas 'y' null', y 'las negativas. 'nil' es, por ejemplo, objeto,' Nil' es para el objeto de clase, 'NULL' es para cualquier otra cosa. Dado que '& error' es la dirección de memoria, no el objeto, use' NULL' – Philip007

Respuesta

13

En primer lugar, la siguiente línea, no tiene mucho sentido:

NSDictionary *attribs = [[NSFileManager defaultManager] 
removeItemAtPath:fullPath error:&error]; 

-removeItemAtPath:error: devuelve un valor BOOL, no un diccionario.

Creo que veo lo que te estás preguntando con el valor NULL. Observe cuidadosamente sin embargo, como hay 2 * 's en el parámetro de error en la firma del método:

- (BOOL)removeItemAtPath:(NSString *)path error:(NSError **)error 

Eso significa un puntero a un puntero. Cuando pasa en &error, está pasando la dirección del puntero al NSError.(Ugh, alguien más probablemente pueda ayudarme aquí, ya que mi cabeza aún comienza a nadar cuando se trata de punteros a punteros). En otras palabras, aunque haya configurado error en nil, no está pasando error al método, está pasando &error.

lo tanto, aquí es lo que el método de re-escrito debe verse como:

// If you want error detection: 
NSError *error = nil; 
if (![[NSFileManager defaultManager] removeItemAtPath:fullPath 
      error:&error]) { 
    NSLog(@"failed to remove item at path; error == %@", error); 
    // no need to log userInfo separately 
    return; 
} 

// If you don't: 
if (![[NSFileManager defaultManager] removeItemAtPath:fullPath 
      error:NULL]) { 
    NSLog(@"failed to remove item at path"); 
    return; 
} 
+0

¡Buena captura sobre el método de devolver BOOL! Eché de menos eso. –

0

No Lo hago de la misma manera y funciona bien para detectar errores. No le está pasando NULL, le está pasando un puntero a NULL, que es algo muy diferente. Aunque es posible que desee agregar otra opción.

if (error != nil){... 
}else{ 
    [NSApp presentError:error] 
} 
9

Pasando NULL significa lo siguiente:

BOOL itemRemoved = [[NSFileManager defaultManager] removeItemAtPath:fullPath 
    error:NULL]; 

es decir, el parámetro de error es NULL. Internamente, -removeItemAtPath:error: ve si se pasó un puntero válido. Si es NULL, simplemente no informará el error como una instancia de NSError, pero el valor de retorno indicará si el método se completó correctamente.

Además, su prueba es incorrecta. No debe utilizar el parámetro de salida error para detectar si se produjo un error porque podría establecerse incluso si el método se completa con éxito. En su lugar, debe usar el valor de retorno del método para detectar errores. Si el valor de retorno (en este caso particular) es NO, a continuación, utilizar el parámetro error de salida para obtener información acerca del error:

NSError *error = nil; 
BOOL itemRemoved = [[NSFileManager defaultManager] removeItemAtPath:fullPath error:&error]; 
if (itemRemoved == NO) { 
    DLogErr(@"Unable to remove file: error %@, %@", error, [error userInfo]); 
    return; 
} 

Citando al Error Handling Programming Guide,

Important: Success or failure is indicated by the return value of the method. Although Cocoa methods that indirectly return error objects in the Cocoa error domain are guaranteed to return such objects if the method indicates failure by directly returning nil or NO, you should always check that the return value is nil or NO before attempting to do anything with the NSError object.


Editar : Como NSGod señaló, -removeItemAtPath:error: devuelve BOOL, no NSDictionary *. He editado mi respuesta para reflejar eso también.

+0

+1 para awesomenessitude impresionante –

+0

Gran explicación, muchas gracias. ¿Tiene un pequeño ejemplo de cómo podría ser el código de detección en la llamada? ¿Es t debido a la declaración de error (NSError **) que es posible diferenciar entre un puntero a nil y nil? – EtienneSky

+0

@EtienneSky Mi respuesta muestra cómo detectar si se produjo un error inspeccionando el valor de retorno. La respuesta de NSGod también lo hace, pero sin usar una variable para almacenar el valor de retorno. Y sí, 'NSError **' le permite diferenciar entre un objeto 'nil' (' NSError * ') y un puntero a un objeto' NSError * '(es decir,' NSError ** '), que podría ser un puntero válido o 'NULL' para indicar que no es necesario almacenar un objeto en el parámetro de salida. –

Cuestiones relacionadas