Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift: Natively Detect if App has Crashed

I have searched around, but have yet to find an answer that doesn't direct me towards a 3rd party service. I do not need anything intricate, just to save a value in NSUserDefaults so when the app opens next, I can display an alert saying the app has crashed.

Thanks.

like image 207
zennox Avatar asked May 13 '16 22:05

zennox


2 Answers

Thanks to a little help from @RyanCollins, I was able to solve the problem myself. The function applicationWillTerminate in the App Delegate only runs when the app closes properly. The code to natively detecting an app crash looks like this.

Globally Defined Variables

let crashedNotificationKey = "com.stackoverflow.crashNotificationKey"
var crashedLastTime = true

App Delegate

func applicationWillTerminate(application: UIApplication) {
    crashedLastTime = false
    prefs.setBool(crashedLastTime, forKey: "crash")
}

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    crashedLastTime = prefs.boolForKey("crash")
    if crashedLastTime == true {

        crashedLastTime = false
        prefs.setBool(crashedLastTime, forKey: "crash")
        NSNotificationCenter.defaultCenter().postNotificationName(crashedNotificationKey, object: self)

    } else {

        crashedLastTime = true
        prefs.setBool(crashedLastTime, forKey: "crash")

    }

    return true
}

Root View Controller

override func awakeFromNib() {
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "crashedAlert", name: crashedNotificationKey, object: nil)
}

func crashedAlert() {
    let alert = UIAlertController(title: "The app has crashed!", message: "Sorry about that! I am just a 17 year old highschooler making my first game!", preferredStyle: UIAlertControllerStyle.Alert)
    alert.addAction(UIAlertAction(title: "It's cool bro.", style: UIAlertActionStyle.Default, handler: nil))
    self.presentViewController(alert, animated: true, completion: nil)
}
like image 135
zennox Avatar answered Oct 11 '22 13:10

zennox


FirebaseCrashlytics

If you don't use Fabric because it is deprecated, You need to use following code in your ViewController that was mentioned in Updagte to the Firebase Crashlytics SDK.

I use it like this:

// 1. import Crashlytics
import FirebaseCrashlytics

class YOUR_ROOT_VIEW_CONTROLLER {

   override viewDidLoad(){
       //...

       // 2. register to get the notifications
       self.configCrashlytics()

       // ...
   }

    func configCrashlytics() {
        /* You must set setCrashlyticsCollectionEnabled to false in order to use
        checkForUnsentReportsWithCompletion. */

        Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(false)

        Crashlytics.crashlytics().checkForUnsentReports { hasUnsentReport in
          let hasUserConsent = false
          // ...get user consent.

          if hasUserConsent && hasUnsentReport {
            Crashlytics.crashlytics().sendUnsentReports()
          } else {
            Crashlytics.crashlytics().deleteUnsentReports()
          }
        }

        // Detect when a crash happens during your app's last run.
        if Crashlytics.crashlytics().didCrashDuringPreviousExecution() {
          // ...notify the user.
            DispatchQueue.main.async {
                let alert = Utils.shared.errorAlert(title: "Sorry!", message: "This App was crashed during last run")
                self.present(alert, animated: true, completion: nil)
            }
        }
        
    }
    // 4. Add a button that run fatallError()
    @IBAction func crashApp(_ sender: UIButton) {
        fatalError()
    }
}

like image 33
Esmaeil Avatar answered Oct 11 '22 13:10

Esmaeil