Splendf
Splendf

Reputation: 1661

Warning: Attempt to present * on * which is already presenting (null)

This is my first application for iOS.

So I have a UIVIewController with a UITableView where I have integrated a UISearchBar and a UISearchController in order to filter TableCells to display

override func viewDidLoad() {
    menuBar.delegate = self
    table.dataSource = self
    table.delegate = self
    let nib = UINib(nibName: "ItemCellTableViewCell", bundle: nil)
    table.registerNib(nib, forCellReuseIdentifier: "Cell")

    let searchButton = UIBarButtonItem(barButtonSystemItem: .Search, target: self, action: "search:")
    menuBar.topItem?.leftBarButtonItem = searchButton
    self.resultSearchController = ({
        let controller = UISearchController(searchResultsController: nil)
        controller.searchResultsUpdater = self
        controller.dimsBackgroundDuringPresentation = false
        return controller
    })()
    self.table.reloadData()
}

I am using also a modal segue in order to open the element's ViewController where I will display details of the element.

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    self.index = indexPath.row
    self.performSegueWithIdentifier("ItemDetailFromHome", sender: self)
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if (segue.identifier == "ItemDetailFromHome") {
        let settingsVC = segue.destinationViewController as! ItemDetailViewController
        settingsVC.parent = self
        if self.isSearching == true  && self.searchText != nil && self.searchText != ""  {
            settingsVC.item = self.filteredItems[self.index!]
        } else {
            settingsVC.item = self.items[self.index!]
        }

    }
}

That works fine until I try to display the ItemDetailViewController for a filtered element (through the UISearchController).

I have the following message :

Warning: Attempt to present <ItemDetailViewController: *>  on <HomeViewController: *> which is already presenting (null)

At every time I am going to the ItemDetailViewController.viewDidLoad() function but after that when the search is activated I have the previous error.

Any idea ? I have tried to use the following async dispatch but without success

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    self.index = indexPath.row
    dispatch_async(dispatch_get_main_queue(), { () -> Void in
        self.performSegueWithIdentifier("ItemDetailFromHome", sender: self)
    })
}

Upvotes: 80

Views: 75709

Answers (19)

Swornim Shah
Swornim Shah

Reputation: 69

Lets say you wanna present AViewController

  1. Simply use self.present(AViewController_object)
  2. Use self.presentedViewController.present(AnotherController_object)

This way you actually present in a stack of one another

self.presentedViewController is the current controller who presented new controller

Upvotes: 0

zef_s
zef_s

Reputation: 77

This one fixed the error, but I still have to double-click the button to call VC. Button unavailable for a few ms. ((

let secondTVC = SecondTVC()
@objc func secondBtnAction() {
    DispatchQueue.main.async { [weak self] in
        guard let self = self else { return }
        if self.presentedViewController == nil {
            let modalNav = UINavigationController(rootViewController: self.secondTVC)
            self.navigationController?.show(modalNav, sender: AnyObject.self)
        }
    }
}

Upvotes: 0

Mahdi Giveie
Mahdi Giveie

Reputation: 640

Make sure you Dismiss previous one before presenting new one!

Upvotes: 0

sm&#246;rkex
sm&#246;rkex

Reputation: 336

Building on Mehrdad's answer: I had to first check if the search controller is active (if the user is currently searching):

if self.searchController.isActive {
    self.searchController.present(alert, animated: true, completion: nil)
} else {
    self.present(alert, animated: true, completion: nil)
}

where alert is the view controller to present modally.

Upvotes: 3

Rydell
Rydell

Reputation: 4217

More than likely you have your Search button wired directly to the other view controller with a segue and you are calling performSegueWithIdentifier. So you are opening it twice, which generates the error that tells you "is already presenting."

So don't call performSegueWithIdentifier, and that should do the trick.

Upvotes: 0

Mehrdad
Mehrdad

Reputation: 1208

My problem was that (in my coordinator) i had presented a VC on a VC and then when i wanted to present the next VC(third one), presented the third VC from the first one which obviously makes the problem which is already presenting. make sure you are presenting the third one from the second VC.

secondVC.present(thirdVC, animated: true, completion: nil)

Upvotes: 2

Chris Herbst
Chris Herbst

Reputation: 1271

What worked for me was to add the presentation of the alert to the main thread.

DispatchQueue.main.async {
   self.present(alert, animated: true)
}

The presentation of the current viewController was not complete. By adding the alert to the main thread it can wait for the viewController's presentation to complete before attempting to present.

Upvotes: 8

Mads Mob&#230;k
Mads Mob&#230;k

Reputation: 35970

In my case this was an issue of a button which was duplicated in Interface Builder. The original button had a touch-up handler attached, which also presented a modal view. When I then attached a touch-up handler on the copied button, I forgot to remove the copied handler from the original, causing both handlers to be fired and thus creating the warning.

Upvotes: 0

powertoold
powertoold

Reputation: 1703

My issue was that I was trying to present an alert from a view that wasn't on top. Make sure you present from the top-most viewController.

Upvotes: 1

Hiram Elguezabal
Hiram Elguezabal

Reputation: 151

The problem for me is that I was presenting two modals and I have to dismiss both and then execute some code in the parent window ... and then I have this error... I solved it seting this code in the dismiss o the last modal presented:

self.dismiss(animated: true, completion: {
                self.delegate?.callingDelegate()
            })

in other words instead of just dismiss two times .. in the completion block of the first dismiss call delegate that will execute the second dismiss.

Upvotes: 8

Lahiru Pinto
Lahiru Pinto

Reputation: 1681

I got the same issue when i tried to present a VC which called inside the SideMenu(jonkykong).

first i tried inside the SideMenu and i called it from the delegate to the MainVC both had the same issue.

Solution: dismiss the SideMenu first and present the new VC after will works perfectly!.

Upvotes: 5

Iman Rosstin
Iman Rosstin

Reputation: 2355

For me it was an alert that was interfering with the new VC that I was about to present.

So I moved the new VC present code into the OK part of my alert, Like this :

    func showSuccessfullSignupAndGoToMainView(){

    let alert = UIAlertController(title: "Alert", message: "Sign up was successfull.", preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { action in
        switch action.style{
        case .default:
            // Goto Main Page to show businesses
            let mainStoryboard = UIStoryboard(name: "Main", bundle: Bundle.main)
            let vc : MainViewController = mainStoryboard.instantiateViewController(withIdentifier: "MainViewController") as! MainViewController
            self.present(vc, animated: false, completion: nil)

        case .cancel:
            print("cancel")

        case .destructive:
            print("destructive")

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

Upvotes: 0

Pavel Kataykin
Pavel Kataykin

Reputation: 1557

In my case, I tried too early to show the new UIViewController before closing the previous one. The problem was solved through a call with a slight delay:

DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
     self.callMethod()
}

Upvotes: 14

KarmaDeli
KarmaDeli

Reputation: 648

This is what finally worked for me, as my project didn't exactly have a NavigationVC but instead, individual detached VC's. as xib files

This code produced the bug:

present(alertVC, animated: true, completion: nil)

This code fixed the bug:

 if presentedViewController == nil{
        navigationController?.present(alertVC, animated: true, completion: nil)
    }

Upvotes: 0

Clay Ellis
Clay Ellis

Reputation: 5330

In my case I was trying to present a UIAlertController at some point in the app's lifetime after using a UISearchController in the same UINavigationController.

I wasn't using the UISearchController correctly and forgot to set searchController.isActive = false before dismissing. Later on in the app I tried to present the alert but the search controller, though not visible at the time, was still controlling the presentation context.

Upvotes: 2

Brandon A
Brandon A

Reputation: 8289

This happened with me on our project. I was presenting our log in/log out ViewController as a pop-over. But whenever I tried to log back out again and display the pop-over again, I was getting this logged out in my console:

Warning: Attempt to present UIViewController on <MY_HOME_VIEW_CONTROLLER> which is already presenting (null)

My guess is that the pop-over was still being held by my ViewController even though it was not visible.

However you are attempting to display the new ViewController, the following code I used to solve the issue should work for you:

func showLoginForm() {

    // Dismiss the Old
    if let presented = self.presentedViewController {
        presented.removeFromParentViewController()
    }

    // Present the New
    let storyboard = UIStoryboard(name: "MPTLogin", bundle: Bundle(for: MPTLogin.self))
    let loginVC = storyboard.instantiateViewController(withIdentifier: "LogInViewController") as? MPTLogInViewController
    let loginNav = MPTLoginNav(rootViewController: loginVC!)
    loginNav.modalPresentationStyle = .pageSheet;
    self.present(loginNav, animated: true, completion: nil)
}

Upvotes: 4

grahamparks
grahamparks

Reputation: 16296

In my case, I found my code to present the new viewController (a UIAlertController) was being called twice.

Check this before messing about with definesPresentationContext.

Upvotes: 37

Prasanna Kumar
Prasanna Kumar

Reputation: 21

I faced the same kind of problem What I did is from Interface builder selected my segue Its kind was "Present Modally" and its presentation was "Over current context"

i changed the presentation to "Default", and then it worked for me.

Upvotes: 2

Splendf
Splendf

Reputation: 1661

I have found out a solution.

I have add the following code in HomeViewController.viewDidLoad and that works !

definesPresentationContext = true

Upvotes: 85

Related Questions