警告:尝试显示已经呈现的* on *(null)

时间:2015-09-21 13:32:54

标签: ios swift uitableview uiviewcontroller uistoryboardsegue

这是我的第一个iOS应用程序。

所以我有UIVIewController UITableView我已经集成UISearchBarUISearchController以过滤要显示的TableCell

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()
}

我也使用模态segue来打开元素的ViewController,我将在其中显示元素的详细信息。

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!]
        }

    }
}

在我尝试显示已过滤元素的ItemDetailViewController(通过UISearchController)之前,这样可行。

我有以下消息:

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

每次我要进入ItemDetailViewController.viewDidLoad()功能,但在此之后,当搜索被激活时,我有上一个错误。

有什么想法吗?我试图使用以下异步调度但没有成功

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

17 个答案:

答案 0 :(得分:59)

我找到了解决方案。

我在HomeViewController.viewDidLoad中添加了以下代码,这有效!

definesPresentationContext = true

答案 1 :(得分:21)

在我的情况下,我发现我的代码呈现了新的viewController(一个UIAlertController)被调用了两次。

在弄乱definesPresentationContext之前检查一下。

答案 2 :(得分:9)

就我而言,在关闭上一个UIViewController之前,我尝试过早地展示它。通过一个稍有延迟的电话即可解决该问题:

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

答案 3 :(得分:2)

我遇到了同样的问题 我所做的是来自Interface builder选择了我的segue 它的类型是“现代模式” 它的陈述是“过度背景”

我将演示文稿更改为“默认”,然后它对我有效。

答案 4 :(得分:2)

我的项目发生了这件事。我作为弹出窗口呈现我们的登录/注销ViewController。但每当我尝试再次注销并再次显示弹出窗口时,我就会在我的控制台中将其注销:

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

我的猜测是,我的ViewController仍然保留了弹出窗口,即使它不可见。

但是,您尝试显示新的ViewController,以下用于解决问题的代码应该适合您:

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)
}

答案 5 :(得分:2)

就我而言,在同一UIAlertController中使用UISearchController后,我尝试在应用程序生命周期的某个时刻出现UINavigationController

我没有正确使用UISearchController而忘记在解雇之前设置searchController.isActive = false。稍后在应用程序中我尝试显示警报,但搜索控制器虽然当时不可见,但仍在控制演示文稿上下文。

答案 6 :(得分:2)

我的问题是(在我的协调人中)我在VC上展示了一个VC,然后当我想展示下一个VC(第三个)时,又展示了第一个VC。显然会导致问题which is already presenting的一个。 确保您要展示第二个VC中的第三个。

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

答案 7 :(得分:0)

确保在展示新的之前先关闭上一个!

答案 8 :(得分:0)

Mehrdad的答案为基础:我必须首先检查搜索控制器是否处于活动状态(如果用户当前正在搜索):

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

其中alert是要模态显示的视图控制器。

答案 9 :(得分:0)

很有可能您将搜索按钮直接通过segue 连接到另一个视图控制器,并且您正在调用performSegueWithIdentifier。因此,您要打开它两次,这会产生一个错误,告诉您“已经在显示”。

所以不要调用performSegueWithIdentifier,那样就可以解决问题。

答案 10 :(得分:0)

对我有用的是将警报的呈现添加到主线程中。

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

当前viewController的演示不完整。通过将警报添加到主线程,它可以等待viewController的演示完成之后再尝试演示。

答案 11 :(得分:0)

就我而言,这是一个在Interface Builder中重复的按钮问题。原始按钮上装有触摸处理程序,该按钮还提供了模式视图。然后,当我在复制的按钮上附加一个修饰处理程序时,我忘了从原始操作中删除复制的处理程序,导致两个处理程序均被触发,从而产生警告。

答案 12 :(得分:0)

我的问题是,我试图从一个不在最上面的视图中发出警报。确保您从最顶部的viewController出现。

答案 13 :(得分:0)

对我来说,问题是我提出了两种模式,必须先关闭这两种模式,然后在父窗口中执行一些代码...然后出现此错误...我解决了在dismiss中设置此代码的问题o呈现的最后一个模态:

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

换句话说,而不是在将执行第二次解除的第一个解除呼叫委托的完成块中仅解除两次。

答案 14 :(得分:0)

当我尝试展示一个在 SideMenu (jonkykong)内部调用的VC时,我遇到了同样的问题。

首先,我在SideMenu内部尝试了一次,然后从委托人到MainVC的调用都遇到了同样的问题。

解决方案: 先关闭SideMenu,然后显示新的VC即可正常运行。

答案 15 :(得分:0)

对我来说,这是一个警报,干扰了我将要展示的新VC。

所以我将新的VC present代码移到了警报的OK部分,就像这样:

    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)
}

答案 16 :(得分:0)

这最终对我有用,因为我的项目并没有完全具有NavigationVC,而是个人独立的VC。作为xib文件

此代码产生了错误:

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

此代码修复了错误:

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