Trying to load view controller view while it is free ... UISearchController

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

Immediately after closing is completed, this warning appears on 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 do not understand what I am doing wrong. This similar question is not really my situation (at least I don't think so). What's happening?

+77
ios swift uisearchcontroller
Aug 29 '15 at 3:23
source share
13 answers

The UISearchController view must be removed from its supervisor before being released. (suppose this is a mistake)

Objective-C ...

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

Swift 3 ...

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

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

+115
05 Oct '15 at 18:52
source share

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

 class ViewController: UITableViewController, UISearchResultsUpdating, UISearchBarDelegate { var resultSearchController = UISearchController() 

:

  class ViewController: UITableViewController, UISearchResultsUpdating, UISearchBarDelegate { var resultSearchController: UISearchController! 

This fixes the problem.

+36
Aug 29 '15 at 13:34 on
source share

Here is the version of Swift that worked for me (similar to JJHs answer):

 deinit{ if let superView = resultSearchController.view.superview { superView.removeFromSuperview() } } 
+19
Oct 22 '15 at 12:58
source share
 class SampleClass: UITableViewController, UISearchBarDelegate { private let searchController = UISearchController(searchResultsController: nil) override func viewDidLoad() { super.viewDidLoad() searchController.loadViewIfNeeded() // Add this line before accessing searchController } } 
+11
May 31 '16 at 11:08
source share

Hacking a few solutions that I managed to run by adding lines to the viewDidLoad before I fully configured 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() } 
+10
Nov 16 '15 at 11:48
source share

In Swift2, I received the same error message due to an obvious error:

 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 of my copy, I did not include the line self.presentViewController. This caused the same error.

+7
Nov 19 '15 at 15:05
source share

In the Swift 2.2 version that worked for me

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

I think this is useful!

+7
May 8 '16 at 8:56 a.m.
source share

Creating a search controller in viewDidLoad() and setting its search string, since presenting the title of the navigation element does not create a strong link to the search controller, therefore it is freed.

So instead:

 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 must 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() } 
+2
Jul 01 '16 at 11:43
source share

My works 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

+2
Sep 21 '16 at 20:26
source share

I used Derek's answer, but I had to change it slightly. The answer that was provided crashed about me because the call to loadViewIfNeeded () occurred before the resultSearchController definition. (My ad was

 var resultSearchController: UISearchController! 

) So I just moved it, and it worked.

If I completely refused the call, the error remained, so I am sure that this is an integral part of the answer. I could not test it on iOS 8.

+1
Jan 18 '16 at 22:38
source share

It's not a mistake. It seems that you need to avoid creating ViewControllers without introducing them. So after SomeViewController() or let variable: SomeViewController you need to call something like this self.presentViewController(yourViewController ...etc) . If you do not, you will receive this warning when this controller is processed.

+1
Feb 15 '16 at 21:12
source share

It seems that the view is lazy, if you select the controller and never show it, the view does not load. In this case, if the controller is freed, you will receive this warning. you can show it once or call the loadViewIfNeed () method or use 'let _ = controller.view' to force the view to load to avoid this warning.

+1
Oct 12 '16 at 9:03
source share

I'm a little late to the party, but here is 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 this works for you.

0
Feb 25 '16 at 6:53
source share



All Articles