Попытка загрузить представление контроллера просмотра во время его освобождения... UISearchController
У меня есть код, который создает UISearchController' in my UIVIew's
viewDidLoad`.
self.resultSearchController = ({
let controller = UISearchController(searchResultsController: nil)
controller.searchResultsUpdater = self
controller.searchBar.delegate = self
controller.dimsBackgroundDuringPresentation = false
controller.searchBar.sizeToFit()
controller.hidesNavigationBarDuringPresentation = false //prevent search bar from moving
controller.searchBar.placeholder = "Search for song"
self.myTableView.tableHeaderView = controller.searchBar
return controller
})()
Сразу после завершения закрытия это предупреждение появляется на консоли:
Attempting to load the view of a view controller while it is deallocating is not allowed and may result in undefined behavior (<UISearchController: 0x154d39700>)
Я не понимаю, что я делаю неправильно. Этот аналогичный вопрос на самом деле не моя ситуация (по крайней мере, я так не думаю). Что происходит?
Ответы
Ответ 1
Представление UISearchController должно быть удалено из своего супервизора перед освобождением. (предположим, что это ошибка)
Objective-C...
-(void)dealloc {
[searchController.view removeFromSuperview]; // It works!
}
Swift 3...
deinit {
self.searchController.view.removeFromSuperview()
}
Я боролся с этой проблемой в течение пары недель. ^^
Ответ 2
Решено! Это было простое решение. Я изменил этот код
class ViewController: UITableViewController, UISearchResultsUpdating, UISearchBarDelegate {
var resultSearchController = UISearchController()
:
class ViewController: UITableViewController, UISearchResultsUpdating, UISearchBarDelegate {
var resultSearchController: UISearchController!
Это устраняет проблему.
Ответ 3
Вот версия Swift, которая работала для меня (похоже на ответ JJHs):
deinit{
if let superView = resultSearchController.view.superview
{
superView.removeFromSuperview()
}
}
Ответ 4
class SampleClass: UITableViewController, UISearchBarDelegate {
private let searchController = UISearchController(searchResultsController: nil)
override func viewDidLoad() {
super.viewDidLoad()
searchController.loadViewIfNeeded() // Add this line before accessing searchController
}
}
Ответ 5
Взломав несколько решений, которые мне удалось запустить, добавив строки в viewDidLoad, прежде чем полностью настроить UISearchController:
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.rightBarButtonItem = self.editButtonItem()
if #available(iOS 9.0, *) {
self.resultSearchController.loadViewIfNeeded()// iOS 9
} else {
// Fallback on earlier versions
let _ = self.resultSearchController.view // iOS 8
}
self.resultSearchController = ({
let controller = UISearchController(searchResultsController: nil)
controller.searchResultsUpdater = self
controller.dimsBackgroundDuringPresentation = false
controller.searchBar.sizeToFit()
self.tableView.tableHeaderView = controller.searchBar
return controller
})()
self.tableView.reloadData()
}
Ответ 6
В Swift2 я получил такое же сообщение об ошибке из-за очевидной ошибки:
let alertController = UIAlertController(title: "Oops",
message:"bla.", preferredStyle: UIAlertControllerStyle.Alert)
alertController.addAction(UIAlertAction(title: "Ok",
style: UIAlertActionStyle.Default,handler: nil))
self.presentViewController(alertController, animated: true, completion: nil)
Из-за глупой копии моей копии я не включил строку self.presentViewController. Это вызвало ту же ошибку.
Ответ 7
В версии Swift 2.2, которая работала для меня
deinit {
self.searchController?.view.removeFromSuperview()
}
Я думаю, это полезно!
Ответ 8
Создание контроллера поиска в viewDidLoad()
и установка его строки поиска, поскольку представление заголовка элемента навигации не создает сильной ссылки на контроллер поиска, поэтому он освобожден.
Итак, вместо этого:
override func viewDidLoad() {
super.viewDidLoad()
// Create search controller
let searchController = UISearchController(searchResultsController: nil)
// Add search bar to navigation bar
navigationItem.titleView = searchController.searchBar
// Size search bar
searchController.searchBar.sizeToFit()
}
Вы должны сделать это:
var searchController: UISearchController!
override func viewDidLoad() {
super.viewDidLoad()
// Create search controller
searchController = UISearchController(searchResultsController: nil)
// Add search bar to navigation bar
navigationItem.titleView = searchController.searchBar
// Size search bar
searchController.searchBar.sizeToFit()
}
Ответ 9
Моя работает так:
func initSearchControl(){
searchController = UISearchController(searchResultsController: nil)
if #available(iOS 9.0, *) {
searchController.loadViewIfNeeded()
} else {
let _ = self.searchController.view
}
searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false
definesPresentationContext = true
tableView.tableHeaderView = searchController.searchBar
searchController.searchBar.sizeToFit()
}
searchController.loadViewIfNeeded() решает проблему, но вам нужно вызвать ее после инициализации searchController
Ответ 10
Я использовал ответ Дерека, но мне пришлось слегка его изменить.
Ответ, который был предоставлен, разбился обо мне, потому что вызов loadViewIfNeeded() произошел до определения resultSearchController. (Мое объявление было
var resultSearchController: UISearchController!
). Поэтому я только что переместил его, и это сработало.
Если я полностью отказался от вызова, ошибка осталась, поэтому я уверен, что это неотъемлемая часть ответа. Я не смог проверить его на iOS 8.
Ответ 11
Это не ошибка. Кажется, что вам нужно избегать создания ViewControllers, не представляя их. Поэтому после SomeViewController()
или let variable: SomeViewController
вам нужно вызвать что-то вроде этого self.presentViewController(yourViewController ...etc)
. Если вы этого не сделаете, вы получите это предупреждение, когда этот контроллер будет обработан.
Ответ 12
Кажется, что просмотр ленивый, если вы выделили контроллер и никогда его не показываете, представление не загружается. В этом случае, если контроллер освобожден, вы получите это предупреждение. вы можете показать его один раз или вызвать метод loadViewIfNeed() или использовать 'let _ = controller.view', чтобы принудительно загрузить представление, чтобы избежать этого предупреждения.
Ответ 13
Я немного опаздываю на вечеринку, но здесь мое решение:
var resultSearchController: UISearchController!
override func viewDidLoad()
{
super.viewDidLoad()
self.resultSearchController = ({
let searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false
searchController.searchBar.sizeToFit()
return searchController
})()
self.tableView.tableHeaderView = self.resultSearchController.searchBar
self.tableView.reloadData()
}
Я надеюсь, что это сработает для вас.