restricciones olvide eliminar como codigo iphone ios objective-c ios4 nserror

olvide - ¿Cómo puedo usar NSError en mi aplicación de iPhone?



olvide mi codigo de restricciones iphone 5 (8)

Estoy trabajando para detectar errores en mi aplicación y estoy estudiando el uso de NSError . Estoy un poco confundido acerca de cómo usarlo y cómo poblarlo.

¿Podría alguien proporcionar un ejemplo sobre cómo poblar y luego usar NSError ?


Bueno, está un poco fuera del alcance de la pregunta, pero en caso de que no tenga una opción para NSError, siempre puede mostrar el error de nivel bajo:

NSLog(@"Error = %@ ",[NSString stringWithUTF8String:strerror(errno)]);


Bueno, lo que normalmente hago es que mis métodos que podrían NSError en el tiempo de ejecución tomen una referencia a un puntero NSError . Si algo sale mal en ese método, puedo rellenar la referencia NSError con datos de error y devolver el método a cero.

Ejemplo:

- (id) endWorldHunger:(id)largeAmountsOfMonies error:(NSError**)error { // begin feeding the world''s children... // it''s all going well until.... if (ohNoImOutOfMonies) { // sad, we can''t solve world hunger, but we can let people know what went wrong! // init dictionary to be used to populate error object NSMutableDictionary* details = [NSMutableDictionary dictionary]; [details setValue:@"ran out of money" forKey:NSLocalizedDescriptionKey]; // populate the error object with the details *error = [NSError errorWithDomain:@"world" code:200 userInfo:details]; // we couldn''t feed the world''s children...return nil..sniffle...sniffle return nil; } // wohoo! We fed the world''s children. The world is now in lots of debt. But who cares? return YES; }

Entonces podemos usar el método como este. Ni siquiera se moleste en inspeccionar el objeto de error a menos que el método devuelva nil:

// initialize NSError object NSError* error = nil; // try to feed the world id yayOrNay = [self endWorldHunger:smallAmountsOfMonies error:&error]; if (!yayOrNay) { // inspect error NSLog(@"%@", [error localizedDescription]); } // otherwise the world has been fed. Wow, your code must rock.

Pudimos acceder a la NSLocalizedDescriptionKey localizedDescription del error porque establecimos un valor para NSLocalizedDescriptionKey .

El mejor lugar para obtener más información es la documentación de Apple . Realmente es bueno.

También hay un tutorial bonito y sencillo sobre Cocoa Is My Girlfriend .


Gran respuesta Alex. Un problema potencial es la desreferencia nula. Referencia de Apple sobre la creación y devolución de objetos NSError.

... [details setValue:@"ran out of money" forKey:NSLocalizedDescriptionKey]; if (error != NULL) { // populate the error object with the details *error = [NSError errorWithDomain:@"world" code:200 userInfo:details]; } // we couldn''t feed the world''s children...return nil..sniffle...sniffle return nil; ...


Intentaré resumir la gran respuesta de Alex y el punto de jlmendezbonini, agregando una modificación que hará que todo sea compatible con ARC (hasta ahora no es así desde que ARC se quejará ya que debes devolver id , que significa "cualquier objeto", pero BOOL no es un tipo de objeto).

- (BOOL) endWorldHunger:(id)largeAmountsOfMonies error:(NSError**)error { // begin feeding the world''s children... // it''s all going well until.... if (ohNoImOutOfMonies) { // sad, we can''t solve world hunger, but we can let people know what went wrong! // init dictionary to be used to populate error object NSMutableDictionary* details = [NSMutableDictionary dictionary]; [details setValue:@"ran out of money" forKey:NSLocalizedDescriptionKey]; // populate the error object with the details if (error != NULL) { // populate the error object with the details *error = [NSError errorWithDomain:@"world" code:200 userInfo:details]; } // we couldn''t feed the world''s children...return nil..sniffle...sniffle return NO; } // wohoo! We fed the world''s children. The world is now in lots of debt. But who cares? return YES; }

Ahora, en lugar de verificar el valor de retorno de nuestra llamada de método, verificamos si el error sigue siendo nil . Si no es así tenemos un problema.

// initialize NSError object NSError* error = nil; // try to feed the world BOOL success = [self endWorldHunger:smallAmountsOfMonies error:&error]; if (!success) { // inspect error NSLog(@"%@", [error localizedDescription]); } // otherwise the world has been fed. Wow, your code must rock.


Me gustaría agregar algunas sugerencias más basadas en mi implementación más reciente. He mirado un código de Apple y creo que mi código se comporta de la misma manera.

Las publicaciones anteriores ya explican cómo crear objetos NSError y devolverlos, así que no me molestaré con esa parte. Intentaré sugerir una buena forma de integrar errores (códigos, mensajes) en su propia aplicación.

Recomiendo crear 1 encabezado que sea una visión general de todos los errores de su dominio (es decir, aplicación, biblioteca, etc.). Mi encabezado actual se ve así:

FSError.h

FOUNDATION_EXPORT NSString *const FSMyAppErrorDomain; enum { FSUserNotLoggedInError = 1000, FSUserLogoutFailedError, FSProfileParsingFailedError, FSProfileBadLoginError, FSFNIDParsingFailedError, };

FSError.m

#import "FSError.h" NSString *const FSMyAppErrorDomain = @"com.felis.myapp";

Ahora, cuando utilice los valores anteriores para los errores, Apple creará un mensaje de error estándar básico para su aplicación. Se podría crear un error como el siguiente:

+ (FSProfileInfo *)profileInfoWithData:(NSData *)data error:(NSError **)error { FSProfileInfo *profileInfo = [[FSProfileInfo alloc] init]; if (profileInfo) { /* ... lots of parsing code here ... */ if (profileInfo.username == nil) { *error = [NSError errorWithDomain:FSMyAppErrorDomain code:FSProfileParsingFailedError userInfo:nil]; return nil; } } return profileInfo; }

El mensaje de error estándar generado por Apple ( error.localizedDescription ) para el código anterior tendrá el siguiente aspecto:

Error Domain=com.felis.myapp Code=1002 "The operation couldn''t be completed. (com.felis.myapp error 1002.)"

Lo anterior ya es bastante útil para un desarrollador, ya que el mensaje muestra el dominio donde ocurrió el error y el código de error correspondiente. Sin embargo, los usuarios finales no tendrán idea de qué significa el código de error 1002 , por lo que ahora necesitamos implementar algunos mensajes agradables para cada código.

Para los mensajes de error debemos tener en cuenta la localización (incluso si no implementamos los mensajes localizados de inmediato). He usado el siguiente enfoque en mi proyecto actual:

1) crear un archivo de strings que contendrá los errores. Los archivos de cadenas son fácilmente localizables. El archivo podría verse como el siguiente:

FSError.strings

"1000" = "User not logged in."; "1001" = "Logout failed."; "1002" = "Parser failed."; "1003" = "Incorrect username or password."; "1004" = "Failed to parse FNID."

2) Agregue macros para convertir códigos enteros en mensajes de error localizados. He usado 2 macros en mi archivo Constantes + Macros.h Siempre MyApp-Prefix.pch este archivo en el encabezado del prefijo ( MyApp-Prefix.pch ) para mayor comodidad.

Constantes + Macros.h

// error handling ... #define FS_ERROR_KEY(code) [NSString stringWithFormat:@"%d", code] #define FS_ERROR_LOCALIZED_DESCRIPTION(code) NSLocalizedStringFromTable(FS_ERROR_KEY(code), @"FSError", nil)

3) Ahora es fácil mostrar un mensaje de error fácil de usar basado en un código de error. Un ejemplo:

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:FS_ERROR_LOCALIZED_DESCRIPTION(error.code) delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show];


Otro patrón de diseño que he visto involucra el uso de bloques, que es especialmente útil cuando un método se ejecuta de forma asíncrona.

Digamos que tenemos los siguientes códigos de error definidos:

typedef NS_ENUM(NSInteger, MyErrorCodes) { MyErrorCodesEmptyString = 500, MyErrorCodesInvalidURL, MyErrorCodesUnableToReachHost, };

Definirías tu método que puede generar un error así:

- (void)getContentsOfURL:(NSString *)path success:(void(^)(NSString *html))success failure:(void(^)(NSError *error))failure { if (path.length == 0) { if (failure) { failure([NSError errorWithDomain:@"com.example" code:MyErrorCodesEmptyString userInfo:nil]); } return; } NSString *htmlContents = @""; // Exercise for the reader: get the contents at that URL or raise another error. if (success) { success(htmlContents); } }

Y luego, cuando lo llama, no tiene que preocuparse por declarar el objeto NSError (la finalización del código lo hará por usted), o verificar el valor de retorno. Solo puede proporcionar dos bloques: uno que se llamará cuando haya una excepción y otro que se llamará cuando tenga éxito:

[self getContentsOfURL:@"http://google.com" success:^(NSString *html) { NSLog(@"Contents: %@", html); } failure:^(NSError *error) { NSLog(@"Failed to get contents: %@", error); if (error.code == MyErrorCodesEmptyString) { // make sure to check the domain too NSLog(@"You must provide a non-empty string"); } }];


Por favor, consulte el siguiente tutorial

Espero que te sea útil, pero antes tienes que leer la documentación de NSError

Este es un enlace muy interesante que encontré recientemente ErrorHandling


C objetivo

NSError *err = [NSError errorWithDomain:@"some_domain" code:100 userInfo:@{ NSLocalizedDescriptionKey:@"Something went wrong" }];

Swift 3

let error = NSError(domain: "some_domain", code: 100, userInfo: [NSLocalizedDescriptionKey: "Something went wrong"])