Attempting to load the view of a view controller while it is deallocating... UISearchController

IosSwiftUisearchcontroller

Ios Problem Overview


I have code that creates a 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
        
    })()

Right after this closure finishes, this warning appears in the console:

Attempting to load the view of a view controller while it is deallocating is not allowed and may result in undefined behavior (<UISearchController: 0x154d39700>)

I don't get what I am doing wrong. This similar question is not really my situation (At least I don't think so). What is going on?

Ios Solutions


Solution 1 - Ios

UISearchController's view has to be removed from its superview before deallocate. (guess it is a bug)

Objective-C...

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

Swift 3...

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

I struggled with this issue for a couple of weeks. ^^

Solution 2 - Ios

Solved! It was a simple fix. I changed this code

class ViewController: UITableViewController, UISearchResultsUpdating, UISearchBarDelegate {

    var resultSearchController = UISearchController()

to this:

 class ViewController: UITableViewController, UISearchResultsUpdating, UISearchBarDelegate {

    var resultSearchController: UISearchController!

This fixes the problem.

Solution 3 - Ios

Here is the Swift version that worked for me (similar toJJHs answer):

deinit{
    if let superView = resultSearchController.view.superview
    {
        superView.removeFromSuperview()
    }
}

Solution 4 - Ios

class SampleClass: UITableViewController, UISearchBarDelegate {

private let searchController =  UISearchController(searchResultsController: nil)

 override func viewDidLoad() {
        super.viewDidLoad()

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

}

Solution 5 - Ios

Hacking together a few solutions I managed to get mine working by adding lines to viewDidLoad before fully setting up the 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()
    
}

Solution 6 - Ios

In Swift2 I got the same error message due to an obvious bug:

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)

Due to a stupid copy error from myself, I had not included the self.presentViewController line. This caused the same error.

Solution 7 - Ios

In Swift 2.2 version that worked for me

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

I think it's helpful!

Solution 8 - Ios

It's not a bug. It seems that you have to avoid creating ViewControllers without presenting them. So after SomeViewController() or let variable: SomeViewController you have to call something like this self.presentViewController(yourViewController ...etc). If you don't do that, you will get this warning when this view controller will be dealocated.

Solution 9 - Ios

Creating a search controller in viewDidLoad() and setting its search bar as the navigation item's title view doesn't create a strong reference to the search controller, which is why it's deallocated.

So instead of doing this:

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

You should do this:

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

Solution 10 - Ios

Mine is working like this

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() solves the problem but you need to call it after initializing the searchController

Solution 11 - Ios

I used Derek's answer, but had to change it slightly. The answer that was provided crashed for me because the call to loadViewIfNeeded() happened before the resultSearchController was defined. (My declaration was

var resultSearchController: UISearchController!

). So I just moved it afterwards and it worked.

If I left out the call entirely, the bug remained, so I'm sure it is an essential part of the answer. I was unable to test it on iOS 8.

Solution 12 - Ios

It seem the view is lazy loaded, if you allocated the controller and never show it, the view is not loaded. In this case, if the controller is deallocated, you will received this warning. you could show it once, or call it's loadViewIfNeed() method, or use 'let _ = controller.view' to force load the view to avoid this warning.

Solution 13 - Ios

I'm a bit late to the party, but here's my solution:

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

I hope it works for you.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMortalManView Question on Stackoverflow
Solution 1 - IosJJHView Answer on Stackoverflow
Solution 2 - IosMortalManView Answer on Stackoverflow
Solution 3 - IosnijmView Answer on Stackoverflow
Solution 4 - Iosharsh_vView Answer on Stackoverflow
Solution 5 - IosDerekView Answer on Stackoverflow
Solution 6 - IosVincentView Answer on Stackoverflow
Solution 7 - IosMilos MandicView Answer on Stackoverflow
Solution 8 - IosNikolai IschukView Answer on Stackoverflow
Solution 9 - IosNielsView Answer on Stackoverflow
Solution 10 - Iosmehmetsen80View Answer on Stackoverflow
Solution 11 - IosMichael L. MehrView Answer on Stackoverflow
Solution 12 - IosdavidView Answer on Stackoverflow
Solution 13 - IostitusmagnusView Answer on Stackoverflow