Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UISearchController - Warning Attempting to load the view of a view controller

I am getting the following error.

Attempting to load the view of a view controller while it is deallocating is not allowed and may result in undefined behavior ()

Tried the following solution , but does not work for me Attempting to load the view of a view controller while it is deallocating... UISearchController

A demo project is available at the link.

  1. Tap add button in Master controller, add few time-stamps.
  2. Switch between rows of the Master view controller and you will see the above error.

Code is shown below and can be downloaded from for short time at .

import UIKit

class DetailViewController: UIViewController,UITableViewDataSource,UITableViewDelegate,UISearchResultsUpdating,UISearchBarDelegate {

    @IBOutlet weak var basicTable: UITableView!        
    var tblSearchController:UISearchController!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.    
        self.tblSearchController = UISearchController(searchResultsController: nil)
        self.basicTable.tableHeaderView=self.tblSearchController.searchBar
//      self.tblSearchController.edgesForExtendedLayout = (UIRectEdge.Top )
//      self.tblSearchController.extendedLayoutIncludesOpaqueBars = true
        self.tblSearchController.searchResultsUpdater = self
        self.tblSearchController.searchBar.delegate = self
        self.tblSearchController.searchBar.sizeToFit()
//      self.tblSearchController.searchBar.frame=CGRectMake(0, 0, self.basicTable.frame.size.width, 44.0)
        self.tblSearchController.hidesNavigationBarDuringPresentation=true
        self.tblSearchController.dimsBackgroundDuringPresentation=true
        self.definesPresentationContext=true
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 0
    }

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 0
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let aCell:UITableViewCell! =  tableView.dequeueReusableCellWithIdentifier("123")
        return aCell
    }

    func updateSearchResultsForSearchController(searchController: UISearchController) {
        print("Begin Update = \(NSStringFromCGRect(self.tblSearchController.searchBar.frame)) \(self.tblSearchController.view.frame) ")
    }

    func searchBarTextDidBeginEditing(searchBar: UISearchBar) {
        print("Begin= \(NSStringFromCGRect(searchBar.frame))")
    }

    func searchBarTextDidEndEditing(searchBar: UISearchBar) {
        print("End=\(NSStringFromCGRect(searchBar.frame))")
    }
}
like image 240
NNikN Avatar asked Sep 20 '15 02:09

NNikN


2 Answers

The problem is a bug in UISearchController where it attempts to load its view in its dealloc method. Probably it calls self.view and the author has forgotten that self.view causes the view to be loaded. If the UISearchController has been created but hasn't been used then it doesn't load its view and this problem occurs. In your sample project if you tap in the SearchBar the warning doesn't appear.

The solution is to force it to load its view. In your code there are two places you can do this: viewDidLoad() or deinit. Use one of the suggested lines (loadViewIfNeeded() or _ = .view) not both. If you're on iOS 9 only then probably best is to use the loadViewIfNeeded code in deinit. If you support iOS 8 then load the view manually as shown.

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    self.tblSearchController = UISearchController(searchResultsController: nil)
    // etc. setup tblSearchController       
    self.tblSearchController.loadViewIfNeeded()    // iOS 9
    let _ = self.tblSearchController.view          // iOS 8
}

deinit {
    self.tblSearchController.loadViewIfNeeded()    // iOS 9
    let _ = self.tblSearchController.view          // iOS 8
}
like image 63
PhoneyDeveloper Avatar answered Nov 10 '22 23:11

PhoneyDeveloper


I see this same problem, IOS9 only, and also note this bug report http://www.openradar.me/22250107. It appears there is no solution at present.

like image 38
MichaelR Avatar answered Nov 11 '22 00:11

MichaelR