A.s.ALI
A.s.ALI

Reputation: 2082

iOS Black screen when close modally presented view controller

I have a tabbar controller and suppose if the user goes to 3rd tab and in 3rd view controller, User presses a button and there I present the view controller as modal .

Now if user switched the tab let say tab 1 or 2 without closing the modally presented view controller, and mean while he comes back to tab 3, the user will still able to see the modally presented view controller, now if user closes the modally presented view controller here, then there is a black screen instead of view controller that opened the modally presented view controller.

The possible work around is that I hide the tabbar controller so that user must close modally presented the view controller first. but it is not the requirement right now. Due to some reasons I can not hide bottom tab bar controller.

Please suggest me how to do following

  1. First of all when user switches tab after opening modally presented view controller, so when he closes the modally presented vc he must see the screen at the back
  2. If point no 1 is not possible so when user goes back again to tab 3 (in which he started modally presented VC) there should not be modally presented view controller. In other words when user switched the tab and the modally presented view controller is opened, it must close, before moving to other tab.

Upvotes: 0

Views: 602

Answers (1)

Sandeep Bhandari
Sandeep Bhandari

Reputation: 20379

You can do it with UITabBarControllerDelegate.

Option 1: Creating subclass of UITabBarController

class MyTabBar: UITabBarController, UITabBarControllerDelegate {
    override func viewDidLoad() {
        super.viewDidLoad()
        self.delegate = self
    }

    func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
        if let currentlySelectedViewController = self.viewControllers?[self.selectedIndex] as? YourThirdTabViewController,
           let presentedViewController = currentlySelectedViewController.presentedViewController {
            presentedViewController.dismiss(animated: false, completion: nil)
        }
        return true
    }
}

Here I am assuming that I have my own sub class of UITabBarController which is set as UITabBarControllerDelegate using self.delegate = self in view didLoad.

Option 2: Make TabBarController's ViewController UITabBarControllerDelegate in their ViewDidLoad

If you dont wanna have your own subclass of UITabBarController all you have to do is simply set your self as UITabBarControllerDelegate in each ViewController's ViewDidLoad

You can have a common protocol or extension to UIViewController and confirm UITabBarControllerDelegate to avoid code duplication if you decide to go down the path of not subclassing UITabBarController

protocol TabBarControllerProtocol: UITabBarControllerDelegate where Self: UIViewController {}

extension TabBarControllerProtocol {
    func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
        if let currentlySelectedViewController = self.tabBarController?.viewControllers?[self.tabBarController?.selectedIndex ?? 0] as? SomeViewController,
           let presentedViewController = currentlySelectedViewController.presentedViewController {
            presentedViewController.dismiss(animated: false, completion: nil)
        }
        return true
    }
}

In whichever ViewController, you want this logic to kick in you can say

class SomeViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        self.tabBarController?.delegate = self
    }
}

extension SomeViewController: TabBarControllerProtocol {}

Thats it.

shouldSelect viewController gets called every time user taps on tab to switch.

The if condition checks if ViewController at selectedIndex (already selected not the new one) is viewController of specific interest or not and also checks if this view controller has presented anything or not, if it has presented it will call dismiss on it

This way when user switches tab from 3rd tab to any other tab, if third tab VC has presented another view controller modally it will dismiss it before it switches tab.

Upvotes: 1

Related Questions