2

I'm writing in Swift 3 (latest Xcode)

I'm controlling, if the user is logged in (async tasks checking parameters between device and database).

If the response says, that the device is invalid, I'm showing the login screen. Looks like this:

extension UIViewController {

    func forceLogin() {

        let storyboard = UIStoryboard(name: "Login", bundle: nil)
        let controller = storyboard.instantiateViewController(withIdentifier: "LoginViewController")
        let navController = UINavigationController(rootViewController: controller)

        self.present(navController, animated: true, completion: nil)
    }  
}

Login storyboard looks just like this.

Storyboard example

When user successfully logs in, the function starts:

DispatchQueue.main.async {
    self.dismiss(animated: true, completion: nil)
}

The dismissal may happen in first and second ViewController.

Imagine the situation:

  1. User logs in and comes back to main application after dismissing 2nd VC
  2. Device is being deleted from DB
  3. After check, user needs to log in again
  4. forceLogin() and...

libc++abi.dylib: terminating with uncaught exception of type NSException

It happens when self.present(navController, animated: true, completion: nil) is used.

I have some ideas what may cause the crash but I'm not sure:

  1. Creating navigation controller in code instead in storyboard
  2. Dismiss is not enough - storyboard somehow stays in memory and can't be instantiated again

What can cause the problem and how can I avoid crashing?

If any more info is necessary, please ask.

Bartosz Woźniak
  • 2,065
  • 3
  • 14
  • 31

1 Answers1

2

I always forget this. Remeber to place your interface tasks like this:

DispatchQueue.main.async {
   self.present(navController, animated: true, completion: nil)
}
Bartosz Woźniak
  • 2,065
  • 3
  • 14
  • 31