Предупреждение: Попытка представить * на *, который уже представляет (ноль)
Это мое первое приложение для 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)
}
Убедитесь, что вы отклонили предыдущий, прежде чем показывать новый!