6

Uwaga 1: To pytanie dotyczy dodania paska wyszukiwania UISearchController poza widokiem tabeli, który aktualizuje - NIE jako nagłówek widoku tabeli.Wyświetlanie paska wyszukiwania UISearchController programowo

Uwaga 2: Niektóre próby i błędy doprowadziły mnie do rozwiązania. Proszę zobaczyć mój answer poniżej.

Jestem nowy w rozwoju iOS i walczę o pracę z klasą UISearchController. Mam kontroler widoku, a moim zdaniem widok kontrolera, planuję mieć pasek wyszukiwania nad widokiem tabeli. Chciałbym, aby pasek wyszukiwania był połączony z kontrolerem UISearch. Ponieważ program budujący interfejs nie jest dostarczany z kontrolerem UISearch, dodam sterownik programowo. Po utworzeniu instancji UISearchController próbowałem programowo dodać pasek wyszukiwania kontrolera do mojego widoku, ale nie udało się. Próbowałem ustawić ramkę paska wyszukiwania i nadać mu ograniczenia związane z autolayout, ale żadne z tych rozwiązań nie zadziałało na mnie (tj. Po uruchomieniu aplikacji nic się nie wyświetla). Oto najnowszy kod, który wypróbowałem:

let searchController = UISearchController(searchResultsController: nil) 

    // Set the search bar's frame 
    searchController.searchBar.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 50) 

    // Constraint to pin the search bar to the top of the view 
    let topConstraint = NSLayoutConstraint(item: searchController.searchBar, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Top, multiplier: 1, constant: 0) 
    searchController.searchBar.setTranslatesAutoresizingMaskIntoConstraints(false) 

    self.view.addSubview(searchController.searchBar) 

    self.view.addConstraint(topConstraint) 

Każda pomoc zostanie bardzo doceniona! Dziękuję Ci!

EDIT: Stosując tylko jeden albo ustawienie ramki pasku wyszukiwania lub dajesz to autoLayout ograniczeń (w przeciwieństwie do kombinacji zarówno jak początkowo próbował) wydaje się działać na początku, ale po wstawieniu na pasku wyszukiwania ciebie będą mieć problemy wskazane przez Dwighta. Zostawiłem kod dla tych przypadków na wypadek, gdyby pomocne było porównanie z tym, co aktualnie masz, ale dla działającego rozwiązania zobacz moją odpowiedź poniżej.

Korzystanie ograniczenia autoLayout:

let searchController = UISearchController(searchResultsController: nil) 

    let topConstraint = NSLayoutConstraint(item: searchController.searchBar, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Top, multiplier: 1, constant: (statusBarHeight + navigationBarHeight!)) 
    let leftConstraint = NSLayoutConstraint(item: searchController.searchBar, attribute: NSLayoutAttribute.Left, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Left, multiplier: 1, constant: 0) 
    let rightConstraint = NSLayoutConstraint(item: searchController.searchBar, attribute: NSLayoutAttribute.Right, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Right, multiplier: 1, constant: 0) 
    let heightConstraint = NSLayoutConstraint(item: searchController.searchBar, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 44) 
    searchController.searchBar.setTranslatesAutoresizingMaskIntoConstraints(false) 

    searchController.searchBar.addConstraint(heightConstraint) 

    self.view.addSubview(searchController.searchBar) 

    self.view.addConstraints([topConstraint, leftConstraint, rightConstraint]) 

mam ustawić topConstraint stałej wysokości paska stanu powiększonej wysokości paska nawigacyjnego, jak mój widok kontroler jest wbudowany w kontroler nawigacji.

Regulacja Rama:

let searchController = UISearchController(searchResultsController: nil) 

    searchController.searchBar.frame = CGRect(x: 0, y: (statusBarHeight + navigationBarHeight!), width: self.view.frame.size.width, height: 44) 

    self.view.addSubview(searchController.searchBar) 
+0

spróbuj tego [link1] (http://shrikar.com/swift-ios-tutorial-uisearchbar-and-uisearchbardelegate/), [link2] (http://www.veasoftware.com/tutorials/2015/4/13/search-display-controller-in-swift-xcode-62-ios-82-tutorial) może ci pomóc –

+0

@ Anbu.Karthik dzięki za linki! Pierwszy wydaje się robić to, co chcę, z nieco większym zaangażowaniem budowniczego interfejsu, więc przyjrzę się bliżej. Po drugie używam UISearchDisplayController, który moim zdaniem jest nieaktualny od wersji iOS 8. – kcstricks

+0

Zdarzyło mi się napotkać ten sam problem co ty, ale mam problem po tym, jak użytkownik kliknie na pasku wyszukiwania. W przypadku opcji ramki pasek wyszukiwania przesuwa się poza widok, a widok tabeli jest wyświetlany, ale nie jest poprawnie umiejscowiony. W przypadku opcji ograniczenia aplikacja ulega awarii przy pomocy "Hierarchia widoku nie jest przygotowana na ograniczenie": błąd po kliknięciu. Czy napotkaliście te problemy? – Dwight

Odpowiedz

12

Po pewnym więcej prób i błędów, mam następujące rozwiązanie robocze:

  1. Otwórz Main.storyboard i dodaj do kontrolera widoku wartość UIView o wysokości 44 (domyślna wysokość paska UISearchBar) i UITableView. Ustaw wiązania automatycznego, tak aby UIView był przypięty do dwóch stron i do przewodnika po najlepszym układzie (korzystając z przewodnika po najlepszym układzie, to zadziała, niezależnie od tego, czy kontroler widoku jest osadzony w kontrolerze nawigacyjnym), a widok tabeli jest przypięty do dwie strony, dolny przewodnik układu i jego wierzchołek przypięty do dolnej części UIView.
  2. Połącz UIView i UITableView jako IBOutlets w swoim ViewController.swift. W moim projekcie nazwałem je topView i tableView.
  3. Deklaracja kontrolera wyszukiwania u góry kontrolki ViewController.SWIFT: var searchController: UISearchController!
  4. Następnie w viewDidLoad(), potrzebne będą:

    // Initialize and set up the search controller 
    self.searchController = UISearchController(searchResultsController: nil) 
    self.searchController.searchResultsUpdater = self 
    self.searchController.dimsBackgroundDuringPresentation = false // Optional 
    self.searchController.searchBar.delegate = self 
    
    // Add the search bar as a subview of the UIView you added above the table view 
    self.topView.addSubview(self.searchController.searchBar) 
    // Call sizeToFit() on the search bar so it fits nicely in the UIView 
    self.searchController.searchBar.sizeToFit() 
    // For some reason, the search bar will extend outside the view to the left after calling sizeToFit. This next line corrects this. 
    self.searchController.searchBar.frame.size.width = self.view.frame.size.width 
    

To powinno być! Oczywiście, musisz uczynić swój kontroler widoku UITableViewDatasource, UITableViewDelegate, UISearchBarDelegate, UISearchControllerDelegate i UISearchResultsUpdating i zadbać o wszystkie wymagane metody delegatów, ale jeśli chodzi o pasek wyszukiwania, to działało dla mnie. Proszę komentarz, jeśli masz jakiekolwiek problemy.

+1

"// Z jakiegoś powodu pasek wyszukiwania rozszerzy się poza widok w lewo". Robi to, ponieważ w viewDidLoad() ramki widoków nie są jeszcze obliczane poprawnie, chociaż pasek wyszukiwania dostaje niewłaściwą ramkę, która jest o wiele większa niż powinna być. jeśli chcesz zrobić to poprawnie, zmień sizeToFit() w viewDidAppear lub po zakończeniu widoku. – Fawkes

+0

@Fawkes - dzięki za dane wejściowe. Mam dla ciebie szybkie pytanie: jeśli tak jest, a ramka widoku nie jest jeszcze poprawnie obliczona, gdy wywołuję sizeToFit(), to czy wiesz, dlaczego to działało, aby ustawić szerokość paska wyszukiwania na szerokość widoku na poniższy wiersz kodu? Jeśli ramka widoku nadal nie jest poprawnie obliczona w tym momencie, czy powyższe nie powinno działać? – kcstricks

+0

Niestety nie można znaleźć czegoś bardzo szczegółowego na temat sizeToFit(), ale jak to jest napisane, że -> "Zmienia rozmiar i przenosi widok odbiornika po to, aby zamknąć jego subviews." Prawdopodobnie oznacza to, że silna operacja obliczania ramek odbywa się tak, jak w przypadku "layoutIfNeeded()", więc po wywołaniu "sizeToFit()" uzyskuje się widoki, dla których ramka została obliczona, zanim normalnie by się to stało po "viewDidLayoutSubviews" lub "viewDidAppear". – Fawkes

-1

spróbuj tego:

 let searchController = UISearchController(searchResultsController: nil).searchBar 

     // Set the search bar's frame 
     searchController.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 50) 

     // Constraint to pin the search bar to the top of the view 
     let topConstraint = NSLayoutConstraint(item: searchController, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Top, multiplier: 1, constant: 0) 
//  searchController.setTranslatesAutoresizingMaskIntoConstraints(false) 

     self.view.addSubview(searchController) 
//  self.presentViewController(searchController, animated: true, completion: nil) 

     self.view.addConstraint(topConstraint) 

lub można po prostu to zrobić:

searchController.searchBar.setTranslatesAutoresizingMaskIntoConstraints(false) 
-> searchController.searchBar.setTranslatesAutoresizingMaskIntoConstraints(true) 
+0

Dzięki za pomoc! Jestem nieco zdezorientowany Twoją pierwszą sugestią, ponieważ wydaje się, że po prostu dodajesz pasek wyszukiwania, a nie pasek wyszukiwania powiązany z kontrolerem wyszukiwania. Proszę, popraw mnie jeśli się mylę. Jeśli chodzi o drugą sugestię, ustawienie setTranslatesAutoResizingMaskIntoConstraints na true works powoduje wyświetlenie paska wyszukiwania, o ile określono jego ramkę. Uważam jednak, że ta flaga jest domyślnie prawidłowa, więc myślę, że możesz po prostu określić ramkę i opuścić ten wiersz tak, jak to zrobiłem w EDYCJI 1 mojego posta. – kcstricks

Powiązane problemy