11

Ho una vista non vista tabella con una barra di ricerca al suo interno, e mentre funziona perfettamente, il controller di visualizzazione della ricerca nasconde la vista tabella e si sovrappone a una vista scura quando una stringa vuota si trova nella barra di ricerca. Voglio che mostri i dati precaricati quando la stringa vuota si trova nella barra di ricerca invece di nascondere la vista tabella e sovrapporre la vista in grigio scuro sotto la barra di ricerca. Proprio come funziona la barra di ricerca di Google in Safari per iOS.Mostra risultati di ricerca precaricati?

Ho trovato una domanda simile su StackOverflow prima: UISearchDisplayController - how to preload searchResultTableView, non riuscivo davvero a farlo funzionare.

Non ho problemi a recuperare i dati precaricati e impostare i dati correnti su di esso, ma non sono sicuro di come impedire a displaycontroller di rimuovere searchResultsTableView.

Grazie in anticipo.

risposta

13

Ho finalmente trovato un modo per farlo.

ho scoperto che il searchDisplayController semplicemente rimuove il searchResultsTableView dalla superview, quindi ho solo aggiunto la visualizzazione della tabella di nuovo nel superview ogni volta che il controller del display ha cercato di nascondere la visualizzazione della tabella:

- (void)searchDisplayController:(UISearchDisplayController *)controller didHideSearchResultsTableView:(UITableView *)tableView 
{ 
    // add the tableview back in 
    [self.view addSubview:self.searchDisplayController.searchResultsTableView]; 
} 

e poi ho Hai anche per mostrare la Tableview la prima volta la barra di ricerca viene cliccato, così ho fatto:

- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller 
{ 
    // after the data has been preloaded 
    self.searchResults = self.allItems; 
    [self.searchDisplayController.searchResultsTableView reloadData]; 
} 

- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller 
{ 
    [self.view addSubview:self.searchDisplayController.searchResultsTableView]; 
} 

per me, 'AllItems' è dove ho conservato tutti gli elementi ricercabili e 'searchResults' è dove gli elementi filtrati (dopo la ricerca) è immagazzinato. E, naturalmente, dovresti precaricare gli elementi (ad esempio cronologia delle ricerche) prima di ricaricare i dati.

Non so se questo è un modo carino o meno di farlo in termini di prestazioni e cosa no, ma ha funzionato perfettamente per me, e spero che questo possa essere utile anche per altre persone. Si prega di commentare se c'è un modo migliore per farlo.

+0

grandi cose, grazie per questo – NSTJ

+0

cercato di capire questo fuori da giorni ormai! Grazie per la soluzione! –

+1

Dopo aver testato questa implementazione, ora voglio capire come ottenere che il contenitore dei risultati di ricerca non sfarfallio quando viene aggiunto alla vista. Poiché viene aggiunto tramite il metodo 'searchDisplayControllerDidBeginSearch:', è possibile vedere lo sfondo scuro per una frazione di secondo prima che venga visualizzato 'searchResultsTableView'. Qualche idea su come aggirare questo? Ho provato a spostare la riga di codice in 'searchDisplayControllerDidBeginSearch' al metodo' searchDisplayControllerWillBeginSearch ', ma questo fa sì che lo sfondo scuro venga posto di fronte a 'searchResultsTableView' –

1

Quando si avvia la ricerca viene chiamato questo metodo. Aggiungi la searchResultsTableView e scoprila. Mostrerebbe quindi i tuoi dati già precaricati. Devo avere i dati precaricati perché funzioni.

- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller 
{ 
    CGRect testFrame = CGRectMake(0, self.notesSearchBar.frame.size.height, self.notesSearchBar.frame.size.width, self.view.frame.size.height - self.notesSearchBar.frame.size.height); 
    self.searchDisplayController.searchResultsTableView.frame = testFrame; 
    [self.notesSearchBar.superview addSubview:self.searchDisplayController.searchResultsTableView]; 

// [self.view addSubview:self.searchDisplayController.searchResultsTableView]; 
    controller.searchResultsTableView.hidden = NO; 
} 

-(void) searchDisplayController:(UISearchDisplayController *)controller didHideSearchResultsTableView:(UITableView *)tableView 
{ 
    CGRect testFrame = CGRectMake(0, self.notesSearchBar.frame.size.height, self.notesSearchBar.frame.size.width, self.view.frame.size.height - self.notesSearchBar.frame.size.height); 
    self.searchDisplayController.searchResultsTableView.frame = testFrame; 
    [self.notesSearchBar.superview addSubview:self.searchDisplayController.searchResultsTableView]; 

    // [self.view addSubview:self.searchDisplayController.searchResultsTableView]; 
    controller.searchResultsTableView.hidden = NO; 
} 


-(void) searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller 
{ 
    controller.searchResultsTableView.hidden = YES; 
} 
4

Dopo ore e ore ho finalmente capito una soluzione che funziona in iOS 7

Basta implementare i seguenti due metodi nel UISearchDisplayDelegate

-(void)searchDisplayController:(UISearchDisplayController *)controller didHideSearchResultsTableView:(UITableView *)tableView { 

    // We need to prevent the resultsTable from hiding if the search is still active 
    if (self.searchDisplayController.active == YES) { 
     tableView.hidden = NO; 
    } 
} 

Quando la ricerca si avvia, il searchResultsTableView è essere nascosto automaticamente, quindi dobbiamo visualizzarlo nuovamente

- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller { 

    controller.searchResultsTableView.hidden = NO; 

    // Then we need to remove the semi transparent overlay which is here 
    for (UIView *v in [[[controller.searchResultsTableView superview] superview] subviews]) { 

     if (v.frame.origin.y == 64) { 
      [v setHidden:YES]; 
     } 
    } 

} 
+0

Questo non ha funzionato su iOS7 per me. Invece, ho controllato se (v.alpha <1), sembra il trucco più "sostenibile". –

+0

Ha funzionato per me, bello! –

4

Ho trovato una molto migliore soluzione a questo problema, e sembra funzionare perfettamente su iOS 6 e 7. Anche se è ancora un hack, è un trucco molto più pulito e futuro di quanto sopra. Le altre soluzioni non funzionano in modo coerente e impediscono l'attivazione di alcuni metodi di UISearchDisplayDelegate! Inoltre ho avuto problemi di insorgenza complessi che non ho potuto risolvere con i metodi di cui sopra. Il problema principale con le altre soluzioni è che confondono seriamente i componenti interni di UISearchDisplayController.La mia soluzione si basa sull'osservazione che UISearchDisplayContoller è un UISearchbarDelegate e che la visualizzazione automatica della tabella dei risultati & può essere attivata simulando una pressione di tasto nel campo di ricerca! Quindi:

- (void) searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller 
{ 
    if ([controller respondsToSelector: @selector(searchBar:textDidChange:)]) 
     [(id<UISearchBarDelegate>)controller searchBar: controller.searchBar textDidChange: @" "]; 
} 

Questo codice è a prova di futuro contro schiantarsi controllando risponde al metodo UISearchbarDelegate, e invia spazio @"" per ingannare l'UISearchDisplayController a pensare utente ha digitato una lettera.

Ora se l'utente digita qualcosa e quindi lo cancella, la tabella si oscurerà di nuovo. Le altre soluzioni cercano di aggirare questo facendo qualcosa nel searchDisplayController: didHideSearchResultsTableView: method. Ma questo non ha senso per me, come sicuramente quando annulli la ricerca occorrerà nascondere la tabella dei risultati e potrebbe essere necessario eseguire il codice in questo caso. La mia soluzione per questa parte è quello di creare una sottoclasse (si nota probabilmente potrebbe usare un metodo Swizzled categoria per farlo funzionare ovunque, se necessario, nel progetto):

// privately declare protocol to suppress compiler warning 
@interface UISearchDisplayController (Super) <UISearchBarDelegate> 
@end 

// subclass to change behavior 
@interface GMSearchDisplayController : UISearchDisplayController 
@end 

@implementation GMSearchDisplayController 

- (void) searchBar: (UISearchBar *) searchBar textDidChange: (NSString *) searchString 
{ 
    if (searchString.length == 0) 
     searchString = @" "; 
    if ([super respondsToSelector: @selector(searchBar:textDidChange:)]) 
     [super searchBar: searchBar textDidChange: searchString]; 
} 

@end 

Questo codice funziona intercettando il metodo delegato textDidChange e cambiare nulla o stringhe vuote nella stringa di spazio @ "" che impediscono il normale nascondiglio/oscuramento che si verifica su una barra di ricerca vuota. Se si utilizza questo secondo bit di codice, è possibile modificare il primo bit per passare un nil anziché @ "" poiché questo secondo bit eseguirà la conversione necessaria per @ "".

Nel mio progetto, ho bisogno per gestire il caso che l'utente non digitare uno spazio, così invece di @"" di cui sopra ho usato un gettone definito:

// arbitrary token used internally 
#define SEARCH_PRELOAD_CONDITIONAL @"_#preresults#_" 

E poi gestirlo internamente convertendolo torna alla stringa zero:

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString 
{ 
    if ([searchString isEqualToString: SEARCH_PRELOAD_CONDITIONAL]) 
     searchString = nil; 
} 

Divertiti! :)

2

questo funziona in iOS 8:

- (void)searchDisplayController:(UISearchDisplayController *)controller didHideSearchResultsTableView:(UITableView *)tableView 
{ 
    self.searchDisplayController.searchResultsTableView.hidden = NO; 
} 

- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller 
{ 
    self.searchDisplayController.searchResultsTableView.hidden = NO; 
    [self.searchDisplayController.searchResultsTableView.superview.superview bringSubviewToFront:self.searchDisplayController.searchResultsTableView.superview]; 

    CGRect frame = self.searchDisplayController.searchResultsTableView.frame; 
    self.searchDisplayController.searchResultsTableView.frame = CGRectMake(frame.origin.x, 64, frame.size.width, frame.size.height); 
} 
0

iOS 9 codice funzionante.

- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller { 
    // Bring the search table view to the view's front 
    self.searchDisplayController.searchResultsTableView.hidden = NO; 
    [self.searchDisplayController.searchResultsTableView.superview bringSubviewToFront:self.searchDisplayController.searchResultsTableView]; 
} 

- (void)searchDisplayController:(UISearchDisplayController *)controller didHideSearchResultsTableView:(UITableView *)tableView { 
    // We need to prevent the resultsTable from hiding if the search is still active 
    if (self.searchDisplayController.active == YES) { 
     tableView.hidden = NO; 
    } 
} 
0

Swift 2.0 + versione

func searchDisplayControllerDidBeginSearch(controller: UISearchDisplayController) { 
    controller.searchResultsTableView.hidden = false 
    controller.searchResultsTableView.superview!.bringSubviewToFront(controller.searchResultsTableView) 
} 

func searchDisplayController(controller: UISearchDisplayController, didHideSearchResultsTableView tableView: UITableView) { 
    if ((searchDisplayController?.active) != nil) { 
     tableView.hidden = false 
    } 
} 
Problemi correlati