2010-01-14 9 views
8

Ejemplo: El método de NSManagedObjectContext-save: se declara así:¿Cuál es el error de Point of (NSError **)?

- (BOOL)save:(NSError **)error 

Desde NSError ya es una clase, y pasando un puntero en realidad tendría el efecto de la modificación de este objeto dentro de la implementación de -save:, ¿cuál es el punto de pasar un puntero a un puntero aquí? ¿Cuál es la ventaja/sentido? ejemplo

Uso:

NSError *error; 
if (![managedObjectContext save:&error]) { 
    // Handle the error. 
} 
+3

debe inicializar el error a cero en ese ejemplo – ergosys

+7

No, no hay absolutamente ninguna necesidad de inicializar el error en cero. El valor del error no está completamente definido al regresar del método ** a menos que ** el método devuelva nulo o NO. – bbum

+0

Siempre había inicializado NSErrors en cero, pero creo que estaba equivocado en mi interpretación de cómo se manejaban los errores internamente: http://rentzsch.tumblr.com/post/260201639/nserror-is-hard –

Respuesta

16

Si acaba de pasar un puntero, todo lo que podría hacer el método sería alterar el objeto NSError ya existente al que está apuntando.

Al pasar un puntero a un puntero, puede crear nuevos objetos NSError y dejarle un puntero que los señale.

+5

tipo de. Si pasó una referencia a un NSError existente, la implementación de NSError debería admitir la mutabilidad. Ese sería un contrato API completamente diferente. De lo contrario, correcto. – bbum

+0

Agregué un conjunto relevante de ejemplos sobre esta pregunta. http://stackoverflow.com/questions/16244597/nserror-returned-with-bad-address-why – bbum

3

Permite el método para asignar un nuevo NSError y cambiar el puntero para señalar que, en lugar de tener que modificar el NSError ya se ha señalado a (¿y si no es lo suficientemente grande ?)

+0

Estoy confundido. Si está enviando la dirección a un NSEror nulo, no hay NSError para 'modificar' hasta que cree uno. Además, NSError es inmutable, por lo que no puede editarlo de todos modos según MacMark anterior. Me gustaría poder darle sentido a todas estas respuestas conflictivas. –

3

La ventaja es que no tiene que crear el objeto NSError. A medida que la documentación indica:

"Un puntero a un objeto NSError no es necesario para crear un objeto NSError."

+0

¿Puede proporcionar más aclaraciones sobre esto, con un ejemplo tal vez, porque MacMark anterior dice 'NSError' es inmutable, por lo que su único la elección es crear uno. Supongo que quiere decir que el CALLER no necesita crear un 'NSError'; sin embargo, si se va a devolver un error, entonces CALLED necesita crear un' NSError'. Su respuesta es un poco confusa. –

6

@Anon es correcta. Añadiré: esta es la manera Cocoa de producir errores, en lugar de arrojar excepciones.

En su ejemplo, usted tiene:

NSError *error = nil; 
if (![managedObjectContext save:&error]) { 
    // Handle the error. 
} 

Inmediatamente después de la llamada a save:, si hubo un error, entonces el método save: habrá creado un nuevo NSError objeto, y ha cambiado la variable de error para señalar desde nil al nuevo objeto de error. De esta forma, puede examinar el objeto NSError usted mismo y responder de manera apropiada.

IMO, esto es más limpio que lanzar una excepción (que en mi filosofía solo debería hacerse cuando ocurre algo catastrófico e irrecuperable).

12

Es lo que algunas personas llaman un parámetro de "salida".

No está pasando un puntero a un objeto NSError, está pasando un puntero a una variable local . Esto le da al método llamado la capacidad de modificar su variable local; en este caso, para asignarlo a una instancia NSError.

Quizás lo que es confuso es que la variable local que está pasando al save: es en sí misma un puntero, por lo que el tipo de variable termina siendo un puntero a un puntero.

En pocas palabras, es un puntero a una variable local, y funciona igual si la variable local es int o NSError*.

+0

tiene mucho sentido ahora. ¡gracias a todos! gran cosa ... – openfrog

+0

Me gusta su explicación, pero no tengo educación sobre cómo una variable local nula tiene una dirección válida que puede pasar a otro método. ¿Puedes por favor elaborar en esa pieza –

1

Si acaba de pasar en un puntero, todo el método podría hacer sería alterar la ya existente objeto NSError que que está señalando.

No se puede modificar un objeto NSError.

NSError es inmutable. Esa es la razón por la que necesita el puntero a la variable NSError. Solo puedes crear un nuevo NSError. Por lo tanto, cambia el puntero para apuntar a su NSError recién creado.

Cuestiones relacionadas