How to catch a database exception in ios? - ios

I have searched a lot on the internet on catching an sqlite exception.But all I could come across was this general exception
#catch (NSException *exception) {
}
What type of exception can I use for sqlite exception handling?

Generally, SQLite does not return exceptions for recoverable errors. Rather, it returns an error code which you must check after each operation.
Some "wrapper" APIs for SQLite may return exceptions, but that would be a function of the particular API.

Related

Difference between 'catch(e)' and 'on Exception catch(e)' in dart?

What is the difference between catch(e) and on Exception catch(e) in dart?
AVOID catches without on clauses.
Using catch clauses without on clauses makes your code prone to encountering unexpected errors that won't be thrown (and thus will go unnoticed).
BAD:
try {
somethingRisky()
} catch(e) {
doSomething(e);
}
GOOD:
try {
somethingRisky()
} on Exception catch(e) {
doSomething(e);
}
Link: avoid_catches_without_on_clauses
The } on Exception catch (e) { will catch all thrown objects implementing Exception.
The excludes most errors (which implement Error),
The } catch (e) { will catch all thrown objects, both exceptions and errors - and anything else that might get thrown. Most thrown objects implement either Exception or Error, but that's just a convention. Any non-null object can be thrown.
I'd actually recommend against on Exception as well. Exceptions are not errors, they are intended for functions as an alternative to returning a value, but exceptions are still just as much part of the function API, and you should only be catching the exceptions that you are actually planning to handle. Since Exception itself has no information, you should be catching the subtype that the function is documented as throwing so you can use the available information to handle the exceptional case.
If you are not going to handle it, you might as well treat the exception as an error.
Using only } catch (e) { to catch everything is reasonable in some situations, mainly in framework code which wraps other user code, and needs to make sure a user code error or unhandled exception doesn't take down the entire program.

Throwing an exception from anywhere in project

I want to show alert whenever an exception occured anywhere in my code.
Without enclosing the code that may throw exception.
Everytime when exception occures it shows error in main class. Is that possible to handle from there?
This is normal way of throwing an exception im using:
#try {
// code that may throw exception
}
#catch (NSException * e) {
// show alert
}
#finally {
}
However, I have found an effective work-around - creating my own exception handler (which is also useful for other reasons). First, create a function that will handle the error and output it to the console (as well as whatever else you want to do with it)
void uncaughtExceptionHandler(NSException *exception) {
NSLog(#"CRASH: %#", exception);
NSLog(#"Stack Trace: %#", [exception callStackSymbols]);
// Internal error reporting
}
Next, add the exception handler to your app delegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
// Normal launch stuff
}
If this doesn't work, then there are only two possible reasons:
Something is overwriting your NSSetUncaughtExceptionHandler call (there can be only one handler for your entire app). For example, some 3rd party libraries set their own uncaughtExceptionHandler. So, try setting it at the END of your didFinishLaunchingWithOptions function (or selectively disabling 3rd party libraries). Or better yet, set a symbolic break point on NSSetUncaughtExceptionHandler to quickly see who is calling it. What you may want to do is to modify your current one rather than adding another one.
You're not actually encountering an exception (for example, EXC_BAD_ACCESS is not an exception)
Navigate to Breakpoint panel in Xcode, click "plus" button at the left-bottom to add a new breakpoint, then do this:
build and run your project, Xcode will brings you to the line where exception throws.
If I'm understanding the question correctly, it seems that you're looking for a good way to handle errors in your code that may have been driven by a user action (e.g. invalid data, missing fields in a form, etc.).
The best way to do this would be to use NSError instead of NSException. NSError is generally used to pass information between different code interfaces that are expecting a possible error, where as NSException is more so for errors that are unexpected, or caused by the developer and thus, should be handled during development.
To present an alert from anywhere in your code, you could add a method to your App Delegate and use target-action to pass along your error. That might look like this:
#protocol DLErrorPresentation <NSObject>
- (void)showAlertWithError:(NSError*)error sender:(id)sender
#end
- (void)showAlertWithError:(NSError*)error sender:(id)sender {
// Your alert presentation code
}
// In some view controller or view:
NSError* error;
if(![self somethingThatMayError:error]) {
id<DLErrorPresentation> responder = [self targetForAction:#selector(showAlertWithError:sender:);
[responder showAlertWithError:error sender:self]
}
To provide additional context, here's what Apple says about exceptions in their documentation:
You should reserve the use of exceptions for programming or unexpected runtime errors such as out-of-bounds collection access, attempts to mutate immutable objects, sending an invalid message, and losing the connection to the window server. You usually take care of these sorts of errors with exceptions when an application is being created rather than at runtime.
Instead of exceptions, error objects (NSError) and the Cocoa error-delivery mechanism are the recommended way to communicate expected errors in Cocoa applications.
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Exceptions/Exceptions.html#//apple_ref/doc/uid/10000012i
Although exceptions are commonly used in many programming environments to control programming flow or to signify errors, do not use exceptions in this way in Cocoa and Cocoa Touch applications. Instead, you should use the return value of a method or function to indicate that an error has occurred, and provide information about the problem in an error object.
https://developer.apple.com/library/content/documentation/General/Conceptual/DevPedia-CocoaCore/ExceptionHandling.html#//apple_ref/doc/uid/TP40008195-CH18-SW1
I have added exception handling code inside my main.m.
int main(int argc, char * argv[]) {
#try {
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFrom
Class([AppDelegate class]));
}
} #catch (NSException *exception) {
NSLog(#"exception");
}
}
Its working now.

Is it possible to determine if an Objective-C exception will be caught?

I'm running into a situation in iOS (and OS X) where exceptions from NSKeyedUnarchiver cause binary-only third-party frameworks to crash my app (when deployed in the field) when they try to unarchive a corrupt archive, thus forcing users to delete and reinstall the app. This doesn't happen often, but I'd like that number to be zero.
I can't solve the problem by wrapping the NSKeyedUnarchiver calls, both because I don't have the source code and because those calls are not the direct result of anything that my code does; they run on arbitrary background threads at arbitrary times.
I'm currently swizzling the NSKeyedUnarchiver class so that reading a corrupt archive returns nil (as though the file were not there) rather than throwing an exception, but I can't be certain whether any of those third-party frameworks might do things correctly (with an #try/#catch block) and might break in interesting ways if I do so.
It would be helpful if I could somehow examine the Objective-C exception handling tree (or equivalent) to determine whether an exception handler would catch an exception if thrown, and if so, which handler. That way, my patched method could return nil if the exception would make it all the way up to Crashlytics (which would rethrow it, causing a crash), but could rethrow the exception if some other handler would catch it.
Is such a thing possible, and if so, how?
Why not wrap your exception-throwing callsite in a try/catch/finally?
#try {
//call to your third party unarchiver
}
#catch {
//remove your corrupted archive
}
#finally {
//party
}
Rolling your own global exception handler may also be of use here, ala: How do you implement global iPhone Exception Handling?
If you're not sure that wrapping third-party library code with #try/#catch is good enough you can hook NSKeyedUnarchiver methods to replace them with exact same wrapper thus making sure that exception is never gets thrown outside. Here is pseudo-code:
#try {
//call original NSKeyedUnarchiver implementation
}
#catch {
return nil;
}
Objc runtime has public APIs that can do such a thing

Core Data swallowing uncaught exception

I have run into a disturbing/baffling bug. Core Data seemed to be swallowing its own exception! When using the (super-useful) CoreDataHelper, I had written a badly formed fetch that resulted in a "Unimplemented SQL generation for predicate" exception. That part's simple, what's really weird is that this exception was being caught somewhere and swallowed, meaning that my code just skipped the rest of the method after that fetch and returned to the main loop without any console messages. Quite infuriating.
Eventually I was able to wrap the actual fetch request in a #try statement and #catch the exception:
#try{
fetchResults = [managedObjectContext executeFetchRequest:request error:&error];
NSLog(#"fetch successful");
}
#catch (NSException* exception) {
NSLog(#"caught exception!\n\n%#\n\n%#\n\n%#",[exception name], [exception reason], [exception userInfo]);
}
This let me figure out what it was, but it still makes no sense that it would be getting caught somewhere. I have not used #try/#catch anywhere else in my code other than to test this.
I also tried creating a blank Core Data project and using CoreDataHelper without the #try/#catch statement to try and isolate the problem, with nothing else in the project, CoreDataHelper works as it should, returning:
CoreDataTest[1044:11603] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unimplemented SQL generation for predicate ("test" LIKE attribute)'
So something in my project is catching and ignoring this exception, but it's not me unless I can somehow do that without using #catch.
What could it be?!
Got it!
I'm using an external accessory (Linea Pro-4 barcode scanner/MSR) that has its own library, and that is what is catching the exception, even in their newest version of the framework.
I set up my blank test project to connect to the accessory before running the same fetch request, and bam! Swallows the exception!

ios error on label

how to soive this to stop warning message for this? am trying to put error on label. Does try catch really prevent crashing app?
#catch (NSException *ex) {
errorLbl.text =ex;
}
Instead of trying to catch a crash, you should make sure that code will not crash altogether. However, you can always convert the NSException to NSString
#catch (NSException *ex) {
errorLbl.text = [NSString stringWithFormat:#"%#",[ex reason]];
}
NSException
#interface NSException : NSObject <NSCopying, NSCoding> {
#private
NSString *name;
NSString *reason;
NSDictionary *userInfo;
id reserved;
}
This question is hard to understand, but if your asking, will that Catch catch every exception that is based off of a NSException, then the answer is yes, with a small issue.
You can catch it, but since your not doing anything about it, the code will continue after the catch. If your app is crashing, then what will happen is you will fill some label with the error, but it wont mean the app is in a stable position, it might just keep crashing.
NSException's reason contains a "human readable" reason that you could display, like:
#catch (NSException *ex) {
errorLbl.text = ex.reason;
}
See the NSException reference for more info.
It's worth noting that exceptions in Objective-C (unlike in other languages) are intended to be used for programming or unexpected runtime errors, not normal program flow. The docs state:
Important: You should reserve the use of exceptions for programming or
unexpected runtime errors such as out-of-bounds collection access,
attempts to mutate immutable objects, sending an invalid message, and
losing the connection to the window server. You usually take care of
these sorts of errors with exceptions when an application is being
created rather than at runtime.
...
Instead of exceptions, error
objects (NSError) and the Cocoa error-delivery mechanism are the
recommended way to communicate expected errors in Cocoa applications.
For further information, see Error Handling Programming Guide.
See the Error Handling Programming Guide.

Resources