Search code examples
iosswiftviewtoast

Create toast when log out (iOS)


I'm working for an app that has users. One of the functionalities is to allow a user to log out and be redirected to the first page. I came across the problem when a user logs out, a toast message "You logged out" should be displayed on the first view of the app and receiving the command from a different page. Basically a toast message that can work with all the views, not only with the current one.

I managed to call a toast function after a user logs out but it won't show the message because the current view is dismissed before to have the chance showing it.

This is the function called:

func showToast(controller: UIViewController, message : String, seconds: Double) {

    let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert)
    alert.view.backgroundColor = UIColor.black
    alert.view.alpha = 0.6
    alert.view.layer.cornerRadius = 15
    controller.present(alert, animated: true)

    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + seconds) {
        alert.dismiss(animated: true)
    }
}

Solution

    1. If you dont know which the current presented VC is you could use this extension here:

      extension UIWindow {
      func topViewController() -> UIViewController? {
          var top = self.rootViewController
          while true {
              if let presented = top?.presentedViewController {
                  top = presented
              } else if let nav = top as? UINavigationController {
                  top = nav.visibleViewController
              } else if let tab = top as? UITabBarController {
                  top = tab.selectedViewController
              } else {
                  break
              }
          }
          return top
      }
      

      }

    Then you can call it it this way:

    if let topVC = UIApplication.shared.keyWindow?.topViewController() {
        topVC.present(alert, animated: true)
    }
    
    1. Another option is that you pop/dismiss your viewcontroller after you dismissed your alert:

      DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + seconds) {
      alert.dismiss(animated: true)
      // popViewController or dismiss here
      }