Search code examples
swiftuiviewcontrolleruinavigationcontrollerswift5

screen freezes if using modalPresentationStyle = .overCurrentContext swift 5


I am presenting a navigation controller with modalPresentationStyle as overCurrentContext. After dismissing controller screen freezes.

I am presenting a FirstViewController with NAvigationController.

let firstVC = FirstViewController.controller()
let nvc = UINavigationController(rootViewController: firstVC)
nvc.modalPresentationStyle = .overCurrentContext
present(nvc, animated: true)

Then inside FirstViewController, I am passing navigationController to push SecondViewController

override func viewDidLoad() {
    super.viewDidLoad()
    guard let nav = navigationController else { return }
    showSecondViewController(parentController: nav)
}

func showSecondViewController(parentController: UINavigationController) {
    let secondVC = SecondViewController.controller()
    parentController.pushViewController(secondVC, animated: true)
}

Now first I am popping SecondViewcontroller on click action from SecondViewController

navigationController?.popViewController(animated: animated)

Then with some call back I am dismissing FirstViewController and NavigationControoler (nvc)

self.controller?.dismiss(animated: true)
self.nvc?.dismiss(animated: true)

Now after dismissing as above I am facing screen freeze issue. I need help to resolve this issue. Please help. Why screen is freezing. Please let me know if I am missing anything here? Thanks


Solution

  • Did you see any errors in the console? I'm not clear about "some call back" as you mentioned above. Can you elaborate?

    I created a small project to replicate your issue. The approach below works fine in my case enter image description here

    • ViewController is the root view controller
    • FirstViewController is the first controller presented on top of ViewController
    • SecondViewController is pushed from the first view controller after the event "ViewDidLoad" happens in FirstViewController

    I also created 1 onViewControllerDissmied callback in each ViewControllers (especially FirstViewController and SecondViewController)

    In ViewController - I created a touch up inside event as below

        @objc func onButtonClicked() {
            let firstVC = FirstViewController()
            nvc = UINavigationController(rootViewController: firstVC)
            guard let nvc = nvc else { return }
            nvc.modalPresentationStyle = .overCurrentContext
            present(nvc, animated: true)
            mycontroller = firstVC
            firstVC.onViewControllerDimissed = { [weak self] in
                self?.mycontroller?.dismiss(animated: true)
                self?.nvc?.dismiss(animated: true)
            }
        }
    

    FirstViewController

    class FirstViewController: UIViewController {
        var label: UILabel = {
            let button = UILabel()
            button.translatesAutoresizingMaskIntoConstraints = false
            button.text = "First View Controller"
            button.textColor = .white
            return button
        }()
        var onViewControllerDimissed: (() -> Void)?
        
        override func viewDidLoad() {
            super.viewDidLoad()
            view.backgroundColor = .purple
            guard let nav = navigationController else { return }
               showSecondViewController(parentController: nav)
        }
    
        func showSecondViewController(parentController: UINavigationController) {
            let secondVC = SecondViewController()
            parentController.pushViewController(secondVC, animated: true)
            secondVC.onViewControllerDimissed = { [weak self] in
                self?.onViewControllerDimissed?()
            }
        }
    }
    

    SecondViewController

    class SecondViewController: UIViewController {
        var label: UILabel = {
            let button = UILabel()
            button.translatesAutoresizingMaskIntoConstraints = false
            button.text = "Second View Controller"
            return button
        }()
        
        var onViewControllerDimissed: (() -> Void)?
        override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
            if let touch = touches.first {
                    let position = touch.location(in: view)
                    let pnt: CGPoint = CGPoint(x: position.x, y: position.y)
                    if (view.bounds.contains(pnt)) {
                        onScreenTouch()
                    }
                }
        }
        
        func onScreenTouch() {
            navigationController?.popViewController(animated: true)
            onViewControllerDimissed?()
        }
    }