Предупреждение: Попытка представить * на *, который уже представляет (ноль)

Это мое первое приложение для iOS.

Итак, у меня есть UIVIewController с UITableView где я интегрировал UISearchBar и UISearchController для того, чтобы отфильтровать TableCells для отображения

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

Я использую также модальный переход, чтобы открыть элемент 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)
    })
}

18 ответов

Я нашел решение.

Я добавил следующий код в HomeViewController.viewDidLoad и это работает!

definesPresentationContext = true

В моем случае я нашел свой код для представления нового viewController (UIAlertControllerназывался дважды.

Проверьте это, прежде чем возиться с definesPresentationContext,

В моем случае я слишком рано пытался показать новый UIViewController перед закрытием предыдущего. Проблема была решена путем звонка с небольшой задержкой:

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

Что сработало для меня, так это добавить представление предупреждения в основной поток.

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

Представление текущего viewController не было завершено. Добавляя предупреждение в основной поток, он может дождаться завершения презентации viewController, прежде чем пытаться представить.

Проблема для меня в том, что я представлял два модальных окна, и я должен отклонить оба, а затем выполнить некоторый код в родительском окне... и затем у меня есть эта ошибка... Я решил, что установил этот код в отклонении последнего модальный представлен:

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

другими словами, вместо того, чтобы просто отклонить два раза.. в блоке завершения первого делегата вызова отклонения, который выполнит второе отклонение.

Я получил ту же проблему, когда я попытался представить VC, который вызывается внутри SideMenu (jonkykong).

сначала я попробовал внутри SideMenu и вызвал его у делегата в MainVC, у обоих была та же проблема.

Решение: сначала распустите SideMenu и представьте новый VC после того, как воля сработает отлично!

Это случилось со мной в нашем проекте. Я представлял наш вход / выход 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)
}

Основываясь на ответе Мехрдада: сначала мне пришлось проверить, активен ли контроллер поиска (если пользователь в данный момент ищет):

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

где alert - это контроллер представления для модального представления.

Моя проблема заключалась в том, что (в моем координаторе) я представил VC на VC а затем, когда я хотел представить следующий VC(третий), представил третий VC из первого, что, очевидно, создает проблему which is already presenting. убедитесь, что вы представляете третий из второгоVC.

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

В моем случае я пытался представить UIAlertController в какой-то момент в жизни приложения после использования UISearchController В то же самое UINavigationController,

Я не использовал UISearchController правильно и забыл установить searchController.isActive = false до увольнения. Позже в приложении я попытался представить предупреждение, но контроллер поиска, хотя и не был видим в то время, все еще контролировал контекст представления.

Я столкнулся с той же самой проблемой. Что я сделал, так это то, что Разработчик интерфейса выбрал мой переход. Его вид был "Представить модально", а его презентация - "В текущем контексте".

Я изменил презентацию на "По умолчанию", и тогда это сработало для меня.

Моя проблема заключалась в том, что я пытался представить предупреждение из представления, которое не было наверху. Убедитесь, что вы представляете из самого верхнего viewController.

Этот исправил ошибку, но мне все равно приходится дважды нажимать кнопку для вызова ВК. Кнопка недоступна в течение нескольких мс. ((

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

Для меня это было предупреждение, которое мешало новому VC, который я собирался представить.

Таким образом, я переместил новый код присутствия VC в часть моего предупреждения 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)
}

Скорее всего, у вас есть кнопка Search, подключенная напрямую к другому контроллеру представления с помощью segue, и вы вызываете performSegueWithIdentifier. Таким образом, вы открываете его дважды, что приводит к ошибке, которая сообщает вам, что "уже отображается".

Так что не вызывайте performSegueWithIdentifier, и это должно помочь.

В моем случае это была проблема кнопки, которая дублировалась в Interface Builder. К исходной кнопке был прикреплен обработчик ретуши, который также представлял модальный вид. Когда я затем прикрепил обработчик ретуши к скопированной кнопке, я забыл удалить скопированный обработчик из оригинала, что привело к срабатыванию обоих обработчиков и созданию предупреждения.

Это то, что, в конце концов, сработало для меня, поскольку у моего проекта точно не было NavigationVC, а вместо этого были отдельные отдельные VC. как файлы XIB

Этот код породил ошибку:

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

Этот код исправил ошибку:

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

Убедитесь, что вы отклонили предыдущий, прежде чем показывать новый!

Другие вопросы по тегам