Mam kod, który tworzy 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
})()
Zaraz po zakończeniu tego zamknięcia w konsoli pojawi się to ostrzeżenie:
Attempting to load the view of a view controller while it is deallocating is not allowed and may result in undefined behavior (<UISearchController: 0x154d39700>)
Nie rozumiem tego, co robię źle. To podobne pytanie nie jest tak naprawdę moją sytuacją (przynajmniej nie sądzę). Co się dzieje?
ios
swift
uisearchcontroller
MortalMan
źródło
źródło
viewDidLoad()
. Zalecamy a) w tym całą listę źródeł VC oraz b) upewnienie się, że błąd rzeczywiście występuje tam, gdzie myślisz, że jest.})()
i po})()
. Błąd jest zgłaszany po zakończeniu zamykania. Mam, aUIViewController
nietableViewController
.Odpowiedzi:
Widok UISearchControllera musi zostać usunięty z jego superviewu przed cofnięciem przydziału. (chyba to błąd)
Cel C...
-(void)dealloc { [searchController.view removeFromSuperview]; // It works! }
Swift 3 ...
deinit { self.searchController.view.removeFromSuperview() }
Zmagałem się z tym problemem przez kilka tygodni. ^^
źródło
UISearchControler
przydzielaniem w-viewDidLoad
. To zdecydowanie błąd - jeśliUISearchController
zostanie zwolniony przed załadowaniem widoku, pojawi się to ostrzeżenie. Jeśli kliknę w pole wyszukiwania (w ten sposób ładuję widok), nie pojawia się. Więc w moimdealloc
dzwonię[self.searchController loadViewIfNeeded]
(nowość w iOS 9),if #available(iOS 9.0, *) { self.searchController?.loadViewIfNeeded() }
[self.searchController loadViewIfNeeded];
(Obj-C) to odpowiedź, która rozwiązała problem w moim kodzie.Rozwiązany! To była prosta poprawka. Zmieniłem ten kod
class ViewController: UITableViewController, UISearchResultsUpdating, UISearchBarDelegate { var resultSearchController = UISearchController()
do tego:
class ViewController: UITableViewController, UISearchResultsUpdating, UISearchBarDelegate { var resultSearchController: UISearchController!
To rozwiązuje problem.
źródło
Oto wersja Swift, która działała dla mnie (podobna do odpowiedzi JJH):
deinit{ if let superView = resultSearchController.view.superview { superView.removeFromSuperview() } }
źródło
if let
ponieważ.removeFromSuperView()
nic nie zrobisz, jeślisuperview == nil
class SampleClass: UITableViewController, UISearchBarDelegate { private let searchController = UISearchController(searchResultsController: nil) override func viewDidLoad() { super.viewDidLoad() searchController.loadViewIfNeeded() // Add this line before accessing searchController } }
źródło
Łącząc kilka rozwiązań, udało mi się uruchomić moje, dodając linie do viewDidLoad przed pełnym skonfigurowaniem 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() }
źródło
self.searchController = ({ let controller = UISearchController(searchResultsController: nil) controller.searchResultsUpdater = self controller.dimsBackgroundDuringPresentation = false controller.searchBar.delegate = self definesPresentationContext = true controller.searchBar.sizeToFit() return controller })()
potemself.searchController.loadViewIfNeeded()
W Swift2 otrzymałem ten sam komunikat o błędzie z powodu oczywistego błędu:
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)
Z powodu popełnionego przeze mnie głupiego błędu kopiowania nie dołączyłem wiersza self.presentViewController. To spowodowało ten sam błąd.
źródło
W wersji Swift 2.2, która działała dla mnie
deinit { self.searchController?.view.removeFromSuperview() }
Myślę, że to pomocne!
źródło
To nie jest błąd. Wygląda na to, że musisz unikać tworzenia ViewControllerów bez ich prezentowania. Więc po
SomeViewController()
lublet variable: SomeViewController
musisz zadzwonić do czegoś takiegoself.presentViewController(yourViewController ...etc)
. Jeśli tego nie zrobisz, otrzymasz to ostrzeżenie, gdy ten kontroler widoku zostanie przydzielony.źródło
Mój tak dział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 () rozwiązuje problem, ale musisz go wywołać po zainicjowaniu searchController
źródło
Utworzenie kontrolera wyszukiwania w programie
viewDidLoad()
i ustawienie jego paska wyszukiwania jako widoku tytułu elementu nawigacji nie tworzy silnego odniesienia do kontrolera wyszukiwania, dlatego jest on cofnięty.Więc zamiast tego robić:
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() }
Powinieneś to zrobić:
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() }
źródło
Użyłem odpowiedzi Dereka, ale musiałem ją nieco zmienić. Podana odpowiedź uległa awarii, ponieważ wywołanie loadViewIfNeeded () miało miejsce przed zdefiniowaniem resultSearchController. (Moja deklaracja brzmiała
var resultSearchController: UISearchController!
). Więc po prostu go przeniosłem i zadziałało.
Jeśli całkowicie pominąłem połączenie, błąd pozostał, więc jestem pewien, że jest to istotna część odpowiedzi. Nie mogłem go przetestować na iOS 8.
źródło
Wygląda na to, że widok jest ładowany z opóźnieniem, jeśli przydzieliłeś kontroler i nigdy go nie pokazałeś, widok nie jest załadowany. W takim przypadku, jeśli kontroler zostanie zwolniony, otrzymasz to ostrzeżenie. możesz to raz pokazać, wywołać metodę loadViewIfNeed () lub użyć 'let _ = controller.view', aby wymusić załadowanie widoku, aby uniknąć tego ostrzeżenia.
źródło
Trochę spóźniłem się na imprezę, ale oto moje rozwiązanie:
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() }
Mam nadzieję, że to zadziała dla ciebie.
źródło