iosswiftpopviewcontroller

popViewControllerAnimated: called on UINavigationController while an existing transition or presentation is occurring


I have a tableview, and as soon as anyone presses a cell, the viewcontroller should pop. This is the code for my tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) method:

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    //previously written code
    navigationController?.popViewController(animated: true)
}

Everything works fine, except for one case: as soon as view loaded, i try to press on any cell immediately. In that situation popViewController isn't executed and i get this error:

popViewControllerAnimated: called on UINavigationController while an existing transition or presentation is occurring; the navigation stack will not be updated.

I know, this question appeared before on StackOverflow, but i didn't find any other solution than:

DispatchQueue.main.asyncAfter(deadline: .now() + //time) {
    navigationController?.popViewController(animated: true)
}

It works great, but i don't need a delay when pressing on tableview cell. As soon as presentation is over, popViewController works as required and delay in execution isn't needed.

Is there another way to make this happen? Or somehow get a notification, when the transition is ready, so i can pop afterwards?


Solution

  • You can use UIViewController's transitionCoordinator.

    Its documentation says:

    When a presentation or dismissal is in progress, this method returns the transition coordinator object associated with that transition. If there is no in-progress transition associated with the current view controller, UIKit checks the view controller’s ancestors for a transition coordinator object and returns that object if it exists. You can use this object to create additional animations and synchronize them with the transition animations.

    let completion = {
        navigationController?.popViewController(animated: true)
    }
    
    guard let coordinator = transitionCoordinator else {
        completion()
        return
    }
    
    coordinator.animate(alongsideTransition: nil) { _ in
        completion()
    }