簡體   English   中英

在取消分配時嘗試加載視圖控制器的視圖... UISearchController

[英]Attempting to load the view of a view controller while it is deallocating… UISearchController

我的代碼UISearchController' in my UIVIew's viewDidLoad`中創建了一個UISearchController' in my UIVIew's

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

我不知道我做錯了什么。 這個類似的問題並不是我的情況(至少我不這么認為)。 到底是怎么回事?

在取消分配之前,必須從其超級視圖中刪除UISearchController的視圖。 (猜猜是個bug)

Objective-C的...

-(void)dealloc { 
    [searchController.view removeFromSuperview]; // It works!
}

斯威夫特3 ......

deinit {
    self.searchController.view.removeFromSuperview()
}

我在這個問題上掙扎了幾個星期。 ^^

解決了! 這是一個簡單的修復。 我改變了這段代碼

class ViewController: UITableViewController, UISearchResultsUpdating, UISearchBarDelegate {

    var resultSearchController = UISearchController()

對此:

 class ViewController: UITableViewController, UISearchResultsUpdating, UISearchBarDelegate {

    var resultSearchController: UISearchController!

這解決了這個問題。

這是適用於我的Swift版本(類似於JJHs答案):

deinit{
    if let superView = resultSearchController.view.superview
    {
        superView.removeFromSuperview()
    }
}
class SampleClass: UITableViewController, UISearchBarDelegate {

private let searchController =  UISearchController(searchResultsController: nil)

 override func viewDidLoad() {
        super.viewDidLoad()

        searchController.loadViewIfNeeded() // Add this line before accessing searchController
 }

}

通過完全設置UISearchController 之前向viewDidLoad添加行來設法讓我的工作變得很有用:

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

}

在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行。 這導致了同樣的錯誤。

在Swift 2.2版本中,對我有用

deinit {
    self.searchController?.view.removeFromSuperview()
}

我覺得它很有幫助!

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

我的工作就是這樣

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后調用它

我使用了Derek的答案,但不得不稍微改變一下。 提供的答案對我來說是崩潰的,因為對loadViewIfNeeded()的調用發生在定義resultSearchController之前。 (我的聲明是

var resultSearchController: UISearchController!

)。 所以我之后移動了它並且它起作用了。

如果我完全省略了電話,那么錯誤仍然存​​在,所以我確信這是答案的重要部分。 我無法在iOS 8上測試它。

這不是一個錯誤。 看來你必須避免創建ViewControllers而不顯示它們。 所以在SomeViewController()let variable: SomeViewController你必須調用類似這樣的self.presentViewController(yourViewController ...etc) 如果不這樣做,則在處理此視圖控制器時將收到此警告。

看起來視圖是延遲加載的,如果你分配了控制器並且從不顯示它,則不加載視圖。 在這種情況下,如果取消分配控制器,您將收到此警告。 您可以顯示一次,或者調用它的loadViewIfNeed()方法,或使用'let _ = controller.view'強制加載視圖以避免此警告。

我參加聚會有點晚了,但這是我的解決方案:

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

我希望這個對你有用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM