J'ai un code qui crée un 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
})()
Dès que cette fermeture est terminée, cet avertissement apparaît dans la 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>)
Je ne comprends pas ce que je fais mal. Cette question similaire n'est pas vraiment ma situation (du moins je ne le pense pas). Que se passe-t-il?
La vue de UISearchController doit être retirée de sa vue avant de désallouer. (devinez que c'est un bug)
Objectif c...
-(void)dealloc {
[searchController.view removeFromSuperview]; // It works!
}
Swift 3 ...
deinit {
self.searchController.view.removeFromSuperview()
}
Je me suis battu avec ce problème pendant quelques semaines. ^^
Résolu! C'était une solution simple. J'ai changé ce code
class ViewController: UITableViewController, UISearchResultsUpdating, UISearchBarDelegate {
var resultSearchController = UISearchController()
pour ça:
class ViewController: UITableViewController, UISearchResultsUpdating, UISearchBarDelegate {
var resultSearchController: UISearchController!
Cela corrige le problème.
Voici la version de Swift qui a fonctionné pour moi (similaire à la réponse deJJH):
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
}
}
En combinant quelques solutions, j'ai réussi à faire fonctionner la mienne en ajoutant des lignes à viewDidLoad before en configurant entièrement 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()
}
Dans la version 2.2 de Swift qui a fonctionné pour moi
deinit {
self.searchController?.view.removeFromSuperview()
}
Je pense que c'est utile!
Dans Swift2, j'ai reçu le même message d'erreur en raison d'un bogue évident:
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)
En raison d'une erreur de copie stupide de ma part, je n'avais pas inclus la ligne self.presentViewController. Cela a causé la même erreur.
Le mien travaille comme ça
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 () résout le problème, mais vous devez l'appeler après l'initialisation de searchController.
La création d'un contrôleur de recherche dans viewDidLoad()
et la définition de sa barre de recherche comme affichage du titre de l'élément de navigation ne créent pas une référence forte au contrôleur de recherche, c'est pourquoi il est désalloué.
Donc au lieu de faire ceci:
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()
}
Vous devriez faire ceci:
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()
}
Ce n'est pas un bug. Il semble que vous deviez éviter de créer des ViewControllers sans les présenter. Donc, après SomeViewController()
ou let variable: SomeViewController
, vous devez appeler quelque chose comme ceci self.presentViewController(yourViewController ...etc)
. Si vous ne le faites pas, vous recevrez cet avertissement lorsque ce contrôleur de vue sera attribué.
J'ai utilisé la réponse de Derek, mais je devais la modifier légèrement ... La réponse fournie m'écrasait, car l'appel à loadViewIfNeeded () s'était passé avant la définition de resultSearchController. (Ma déclaration était
var resultSearchController: UISearchController!
). Alors je l'ai juste déplacé après et cela a fonctionné.
Si je laissais complètement l'appel, le bogue demeurait, alors je suis sûr que c'est un élément essentiel de la réponse. Je n'ai pas pu le tester sur iOS 8.
Il semble que la vue soit chargée par défaut, si vous avez alloué le contrôleur et ne l'avez jamais affiché, la vue n'est pas chargée. Dans ce cas, si le contrôleur est désalloué, vous recevrez cet avertissement. vous pouvez l'afficher une fois ou appeler la méthode loadViewIfNeed () ou utiliser 'let _ = controller.view' pour forcer le chargement de la vue afin d'éviter cet avertissement.
Je suis un peu en retard à la fête, mais voici ma 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()
}
J'espère que cela fonctionne pour vous.