Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Objective c iPhone redirect to error page for uncaught exception

I have a class I want to redirect user to Error page if theres been an: uncaught exception , a caught exception or a custom exception. I also want to flick off an error email. (so that I'm notified).

I can't access the current View Controller within this class (in the case of an uncaught exception). Because its triggered with the delegate listener onUncaughtException(NSException* exception).

How can I access the current view controller, or failing that, modally redirect user to an Error view controller?

#import "ErrorHelper.h"
#import "ErrorViewController.h"
#import "Global.h"
#import "AppDelegate.h"

@implementation ErrorHelper


+(void) handleUncaughtError:(NSException*) exception
{
    NSLog(@"Uncaught exception occurred!");
    
    [self sendErrorEmailIfAppropriate:exception :nil];
    [self redirectToErrorPage];
}

+(void) handleCaughtError:(NSException*) exception
{
    NSLog(@"Error caught!!");
    
    [self sendErrorEmailIfAppropriate:exception :nil];
    [self redirectToErrorPage];
}

+(void) handleCaughtCustomError:(NSString*) ref :(NSString*) details
{
    NSLog(@"Custom error caught!!");
    //can do conditional branching on @ref, to do appropriate action.
    
    [self sendErrorEmailIfAppropriate:nil :details];
    [self redirectToErrorPage];
    
    
}

+(void) sendErrorEmailIfAppropriate:(NSException*) exception :(NSString*)details
{
    if([[Global get] isInTestMode] || [[Global get] isInLiveMode]) {
        bool isCustomException = details != nil;
        
    }
}

+(void) redirectToErrorPage
{
    /*Try redirect user to error page
    E.G:
     -There's been an error, our App Dev team will try and resolve the issue for you
     -Regards -Dev team
     
    */
    AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
    
}

@end

like image 967
williamsandonz Avatar asked Nov 05 '12 02:11

williamsandonz


2 Answers

You should be under the assumption that Cocoa exceptions are non-recoverable. Don't throw them, don't add them to your program. (Using exceptions in C++ is fine, although mixing C++ and ObjC can be unsafe in this regard because ObjC is just not designed for this control flow or cleanup at unwind).

There are a few oddball ObjC APIs which throw, and you could recover from some of them. If possible, use an alternative which does not throw. If you must try/catch in this scenario, then you should make your handler as local to the callsite as possible. Assume an uncaught ObjC exception or one caught by a high level handler is unrecoverable.

Now, because your caught exception is local to the callsite, you can easily add the logic to propagate the error to a view controller or back into the event loop (e.g. an AlertView). Yes, you will likely have some error out parameters or return values to introduce in this case.

Email is a separate question.

like image 78
justin Avatar answered Oct 14 '22 00:10

justin


I tried this from: exception_handler Its working! Just write your email sending code instead of the alert view.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{        
    [window makeKeyAndVisible];

    NSSetUncaughtExceptionHandler(&exceptionHandler);

    return YES;
}

BOOL exceptionAlertDismissed = FALSE;
void exceptionHandler(NSException *exception)
{
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"App Committed Suicide"
        message:@"Oh dear, that wasn't supposed to happen. You will have to restart the application... sorry!"
        delegate:[[UIApplication sharedApplication] delegate] cancelButtonTitle:nil otherButtonTitles:@"That's ok!", @"Erm, bye...", nil];
    [alert show];
    [alert release];

    while (exceptionAlertDismissed == FALSE)
    {
        [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
    }
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    exceptionAlertDismissed = TRUE;
}

In interface,

@interface ...appDelegate : NSObject <UIApplicationDelegate, UIAlertViewDelegate>
...
void exceptionHandler(NSException *exception);
like image 1
Abdullah Umer Avatar answered Oct 14 '22 01:10

Abdullah Umer