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

Я надеюсь, что это сработает для вас.