6

Nota 1: Questa domanda riguarda l'aggiunta di una barra di ricerca di UISearchController al di fuori della tabella per visualizzare gli aggiornamenti, NON come intestazione della vista tabella.Visualizza la barra di ricerca di UISearchController a livello di codice

Nota 2: Alcuni tentativi ed errori mi hanno portato a una soluzione. Si prega di consultare il mio answer qui sotto.

Sono nuovo nello sviluppo di iOS e sto faticando a lavorare con la classe UISearchController. Ho un controller di visualizzazione, e nella mia visualizzazione del controller di visualizzazione, ho intenzione di avere una barra di ricerca sopra una vista tabella. Vorrei che la barra di ricerca fosse collegata a un UISearchController. Poiché il generatore di interfacce non viene fornito con un UISearchController, aggiungo il controller a livello di codice. Dopo aver istanziato un UISearchController, ho provato ad aggiungere la barra di ricerca del controller di ricerca alla mia vista a livello di codice, ma non ho avuto successo. Ho provato a impostare il frame della barra di ricerca e a dargli dei vincoli di autolayout, ma nessuno dei due ha funzionato per me (cioè quando eseguo l'app, non appare nulla). Ecco l'ultimo codice che ho provato:

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) 

Qualsiasi aiuto sarebbe molto apprezzato! Grazie!

EDIT: Utilizzando solo uno di una impostazione telaio della barra di ricerca o si dandogli layout automatico vincoli (in contrapposizione ad una combinazione sia come ho inizialmente provato) sembra funzionare in un primo momento, ma dopo toccando la barra di ricerca si avrà problemi come sottolineato da Dwight. Ho lasciato il codice per questi casi nel caso in cui sia utile fare un confronto con quello che hai attualmente, ma per una soluzione funzionante vedi la mia risposta qui sotto.

Uso vincoli layout automatico:

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]) 

ho impostato il topConstraint costante l'altezza della barra di stato più l'altezza della barra di navigazione, come il mio controller della vista è incorporato in un controller di navigazione.

Regolazione del telaio:

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

prova questo [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) potrebbe esserti d'aiuto –

+0

@ Anbu.Karthik grazie per i link! Il primo sembra fare proprio quello che voglio con un po 'più di coinvolgimento del builder dell'interfaccia, quindi darò un'occhiata più da vicino. Il secondo utilizza UISearchDisplayController, che a mio avviso è deprecato a partire da iOS 8. – kcstricks

+0

Ho riscontrato il tuo stesso problema, tuttavia ho problemi dopo che l'utente ha toccato la barra di ricerca. Con l'opzione frame, la barra di ricerca scorre fuori dalla vista e la tableview viene mostrata ma non posizionata correttamente. Con l'opzione vincoli, l'app si arresta in modo anomalo con "La gerarchia della vista non è pronta per il vincolo:" errore una volta toccato. Hai incontrato anche questi problemi? – Dwight

risposta

12

Dopo un po 'di più tentativi ed errori, ho il seguente soluzione operativa:

  1. Apri Main.storyboard e aggiungi al tuo controller di visualizzazione un UIView con altezza 44 (altezza predefinita di UISearchBar) e UITableView. Imposta i vincoli di autolayout in modo che UIView sia bloccato ai due lati e alla guida di layout in alto (utilizzando la guida di layout in alto assicura che funzioni anche se il controller di visualizzazione è incorporato in un controller di navigazione) e la vista tabella è bloccata su i due lati, la guida di layout in basso e la parte superiore bloccata nella parte inferiore di UIView.
  2. Collegare Uiview e UITableView come IBOutlet in ViewController.swift. Nel mio progetto li ho chiamati topView e tableView.
  3. Dichiarare un controller di ricerca nella parte superiore del ViewController.SWIFT: var searchController: UISearchController!
  4. Poi, in viewDidLoad(), sarà necessario:

    // 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 
    

Questo dovrebbe essere! Ovviamente, dovrai rendere il tuo controller di visualizzazione UITableViewDatasource, UITableViewDelegate, UISearchBarDelegate, UISearchControllerDelegate e UISearchResultsUpdating e prendersi cura di tutti i metodi di delega richiesti, ma per quanto riguarda la barra di ricerca, questo ha funzionato per me. Si prega di commentare se avete problemi.

+1

"// Per qualche motivo, la barra di ricerca si estenderà all'esterno della vista a sinistra". Lo fa perché in viewDidLoad() i frame delle viste non sono ancora calcolati correttamente, anche se la tua barra di ricerca ottiene una cornice sbagliata che è molto più grande di quanto dovrebbe essere. se vuoi fare le cose correttamente, crea sizeToFit() nella tua viewDidAppear o dopo che la tua vista ha finito di impaginare. – Fawkes

+0

@Fawkes - grazie per l'input. Ho una rapida domanda di follow-up per te: se questo è il caso, e il frame della vista non è ancora calcolato correttamente quando chiamo sizeToFit(), sai perché ha funzionato per impostare la larghezza della barra di ricerca sulla larghezza della vista sulla seguente riga di codice? Se il frame della vista non è ancora calcolato correttamente a questo punto, non dovrebbe funzionare quanto sopra? – kcstricks

+0

Purtroppo non riesco a trovare qualcosa di molto dettagliato su sizeToFit(), ma come è scritto che -> "Ridimensiona e sposta la vista del ricevitore in modo che racchiuda solo i suoi subviews." Questo probabilmente significa che un calcolo di frame forzato avviene come nel caso di "layoutIfNeeded()", quindi dopo aver chiamato "sizeToFit()" ottieni viste per le quali è stato calcolato il frame prima che accadesse normalmente come dopo "viewDidLayoutSubviews" o "viewDidAppear". – Fawkes

-1

provare questo:

 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) 

oppure si può semplicemente fare questo:

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

Grazie per il tuo aiuto! Sono un po 'confuso dal tuo primo suggerimento perché questo sembra aggiungere solo una barra di ricerca, piuttosto che una barra di ricerca associata a un controller di ricerca. Perfavore, correggimi se sbaglio. Per quanto riguarda il secondo suggerimento, impostando setTranslatesAutoResizingMaskIntoConstraints su true works per visualizzare la barra di ricerca, purché ne abbia specificato il frame. Tuttavia, credo che questo flag sia vero per impostazione predefinita, quindi penso che puoi semplicemente specificare un frame e lasciare questa riga come ho fatto in EDIT 1 del mio post. – kcstricks