24

I would like for my app to reset to standard settings if it crashed during startup. Preferably also if it crashed last time it was run.

EDIT: Crittercism has a crittercismDidCrashOnLastLoad method, but it only handles the case of crashing during load. It didn't work properly in the version of the library I used, but this has since been fixed.

Suggestions?

Jack
  • 13,571
  • 6
  • 76
  • 98

2 Answers2

39

Make 2 functions in your AppDelegate.m file:

void HandleException(NSException *exception) {
    NSLog(@"App crashing with exception: %@", exception);
    //Save somewhere that your app has crashed.
}

void HandleSignal(int signal) {
    NSLog(@"We received a signal: %d", signal);
    //Save somewhere that your app has crashed.
}

Then in your -(BOOL)application:didFinishLaunchingWithOptions before anything else put:

NSSetUncaughtExceptionHandler(&HandleException);

struct sigaction signalAction;
memset(&signalAction, 0, sizeof(signalAction));
signalAction.sa_handler = &HandleSignal;

sigaction(SIGABRT, &signalAction, NULL);
sigaction(SIGILL, &signalAction, NULL);
sigaction(SIGBUS, &signalAction, NULL);
graver
  • 15,183
  • 4
  • 46
  • 62
  • 2
    Hmm, looks useful. Will it interact badly with Crittercism? – Anders Sewerin Johansen Jun 04 '12 at 20:01
  • 2
    OK, I've tested this, and it will in fact disable Crittercism. I think I'll try to convince them to add this feature to their product then. Thank you for your advice, it was most helpful. – Anders Sewerin Johansen Jun 05 '12 at 13:12
  • Good to know, I haven't used `Crittercism`, but probably they handle it in a similar way, this is also the way `TestFlight` handle the error logging. You can actually ask them how to use their uncaught exception handler together with yours... – graver Jun 05 '12 at 14:04
  • 1
    Well, I wrote them a nice note about it. Will update the comments here when/if I hear from them. – Anders Sewerin Johansen Jun 06 '12 at 10:01
  • 2
    I just tried this out, and I was wondering why HandleSignal() doesn't get called? – max_ Jan 19 '13 at 15:43
  • So @AndersSewerinJohansen, any updates in you talk with the Crittercism team? – newton_guima Feb 10 '13 at 03:44
  • 2
    Why isn't `NSSetUncaughtExceptionHandler` enough, without `SIGABRT`, `SIGKILL`, and `SIGBUS`? – ma11hew28 Oct 22 '13 at 00:55
  • Swift answer - https://stackoverflow.com/questions/25441302/how-should-i-use-nssetuncaughtexceptionhandler-in-swift – Jack May 16 '18 at 06:09
8

Using Crashlytics you then can set CrashlyticsDelegate to detect a crash on Swift or ObjC code.

import Fabric
import Crashlytics
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool
{
    Crashlytics.sharedInstance().delegate = self
    Fabric.with([Crashlytics.self])
    return true
}

//MARK: - CrashlyticsDelegate

func crashlyticsDidDetectReport(forLastExecution report: CLSReport, completionHandler: @escaping (Bool) -> Void)
{
    completionHandler(true)
}

From Crashlytics docs

Your delegate must invoke the completionHandler, but does not need to do so synchronously, or even on the main thread. Invoking completionHandler with NO will cause the detected report to be deleted and not submitted to Crashlytics. This is useful for implementing permission prompts, or other more-complex forms of logic around submitting crashes.

Make certain that the delegate is setup before starting Crashlytics with startWithAPIKey:… or via [Fabric with:…]. Failure to do will result in missing any delegate callbacks that occur synchronously during start.

Igor
  • 4,235
  • 3
  • 34
  • 32
  • The order of the following two lines is important. It will not work if you switch the order. Crashlytics.sharedInstance().delegate = self Fabric.with([Crashlytics.self]) – christopher.online Aug 02 '18 at 15:23