2016-07-27 5 views
11

Ich habe einen Tabellenansicht-Controller mit einer UISearchController, die UISearchBar als tableView.tableHeaderView setzt. Beim Aktualisieren der Suchergebnisse verwende ich die beginUpdates und endUpdates und verwandte Methoden, um die Daten für die Tabellenansicht zu aktualisieren.UISearchBar verschwindet aus tableHeaderView bei Verwendung von beginUpdates/endUpdates

Dadurch wird die Suchleiste ausgeblendet; Die tableHeaderView ist auf eine leere, generische UIView der gleichen Größe wie die Suchleiste festgelegt. Wenn ich einfach reloadData statt der gesamten beginUpdates/endUpdates Prozedur verwenden, ist alles in Ordnung.

Der Tabellenansicht-Controller ist in einen normalen Ansichts-Controller eingebettet. Es ist kein Navigationscontroller beteiligt. Dies ist die vollständige Umsetzung der Tabelle View-Controller notwendig, das Problem zu reproduzieren:

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil]; 
    self.searchController.searchResultsUpdater = self; 
    self.searchController.dimsBackgroundDuringPresentation = NO; 

    self.tableView.tableHeaderView = self.searchController.searchBar; 
} 

- (void)updateSearchResultsForSearchController:(UISearchController *)searchController 
{ 
    [self.tableView beginUpdates]; 
    [self.tableView endUpdates]; 
} 

Warum dies die Suchleiste verursacht mit einer leeren Ansicht ersetzt werden, und wie können sie vermieden werden?

+0

Haben Sie versucht, die "transluzente" Eigenschaft auf Ihrem ViewController/Navigation Controller auf und von? Ich erinnere mich, dass ich dieses Problem einmal hatte, und wenn ich mich richtig erinnere "durchscheinend" hatte es etwas damit zu tun .. – MCMatan

Antwort

0

Wenn Sie zum ersten Mal auf UISearchController's searchBar klicken, dauert es etwa 0,5 Sekunden, bis die searchBar animiert wird. Aber self.tableView.endUpdates() wurde sofort von der Delegate-Methode aufgerufen, die Animation wurde unterbrochen.
Die SearchBar in der Mitte der Animation stecken, und Sie können es UI nicht sehen:
enter image description here

Eine Abhilfe ist zu überprüfen, ob SearchBar in der Animation ist, und self.tableView.endUpdates() verzögern, wenn es in ist.

func updateSearchResultsForSearchController(searchController: UISearchController){ 
    self.tableView.beginUpdates() 
    //Do some updates 

    if !searchController.searchBar.showsCancelButton{ 
     self.tableView.performSelector(#selector(UITableView.endUpdates), withObject: nil, afterDelay: 1) 

    }else{ 
     self.tableView.endUpdates() 
    } 
} 
+0

Vielen Dank für Ihre Antwort. Ich denke, Sie sind auf etwas über Animation. Ich habe versucht Tricks wie '[CATtransaction setCompletionBlock:]', aber ohne Erfolg. Ihr Workaround scheint besonders hacky und funktioniert außerdem nicht für das ursprüngliche Problem. Wahrscheinlich, weil es nicht so künstlich ist wie das reproduzierbare Beispiel, das ich zur Verfügung gestellt habe, und mehr Arbeit zwischen 'beginUpdates' und' endUpdates' leistet. –

+0

In diesem Fall sollten Sie versuchen, Ihren 'UISearchController' mit einem anderen tableViewController zu initialisieren und alle Aktualisierungen mit diesem zweiten tableViewController durchzuführen. – wj2061

+0

Wie in '[[UISearchController alloc] initWithSearchResultsController: ...]'? Ich nehme an, das ist eine Lösung, aber ich möchte alle Funktionen, die mit der ursprünglichen Tabellenansicht verbunden sind, wie Gesten und dergleichen, behalten. Wenn es keinen anderen Weg gibt, gibt es nichts, was ein wenig Refactoring nicht lösen kann. –

0

Kleine Revision über beginUpdates, endUpdates and reloadData

beginUpdates:: Beginnt eine Reihe von Verfahren nennt das Einfügen, Löschen oder wählen Sie Zeilen und Abschnitte der Tabellenansicht. Rufen Sie diese Methode auf, wenn nachfolgende Einfüge-, Lösch- und Auswahlvorgänge (z. B. cellForRowAtIndexPath: und indexPathsForVisibleRows) gleichzeitig animiert werden sollen. Sie können diese Methode auch verwenden, gefolgt von der endUpdates-Methode, um die Änderung der Zeilenhöhen zu animieren, ohne die Zelle neu zu laden. Diese Methodengruppe muss mit einem Aufruf von endUpdates enden. Diese Methodenpaare können verschachtelt sein. Wenn Sie innerhalb dieses Blocks keine Einfüge-, Lösch- und Auswahlaufrufe ausführen, werden Tabellenattribute wie die Zeilenanzahl möglicherweise ungültig. Sie sollten reloadData nicht innerhalb der Gruppe aufrufen. Wenn Sie diese Methode in der Gruppe aufrufen, müssen Sie selbst Animationen ausführen.

endUpdates: Beendet eine Reihe von Methodenaufrufen, die Zeilen und Abschnitte der Tabellenansicht einfügen, löschen, auswählen oder erneut laden. Sie rufen diese Methode auf, um eine Reihe von Methodenaufrufen einzugrenzen, die mit beginUpdates beginnen und Operationen zum Einfügen, Löschen, Auswählen und erneuten Laden von Zeilen und Abschnitten der Tabellenansicht enthalten. Wenn Sie endUpdates aufrufen, animiert UITableView die Vorgänge gleichzeitig. Aufrufe von beginUpdates und endUpdates können verschachtelt werden. Wenn Sie innerhalb dieses Blocks keine Einfüge-, Lösch- und Auswahlaufrufe tätigen, können Tabellenattribute wie die Zeilenanzahl ungültig werden.

reloadData: Lädt die Zeilen und Abschnitte der Tabellenansicht neu. Rufen Sie diese Methode auf, um alle Daten neu zu laden, die zum Erstellen der Tabelle verwendet werden, einschließlich Zellen, Abschnittsheadern und -fußzeilen, Indexarrays und so weiter. Aus Gründen der Effizienz werden in der Tabellenansicht nur die Zeilen angezeigt, die sichtbar sind.Es passt Offsets an, wenn die Tabelle aufgrund des Neuladens schrumpft. Der Delegat oder die Datenquelle der Tabellenansicht ruft diese Methode auf, wenn die Tabellenansicht ihre Daten vollständig neu laden soll. Es sollte nicht in den Methoden aufgerufen werden, die Zeilen einfügen oder löschen, insbesondere innerhalb eines Animationsblocks, der mit Aufrufen von beginUpdates und endUpdates implementiert wurde.

nun bei der Suche wissen wir nicht, welche Zeilen als auch jedes Mal Suchergebnisdaten anders wäre beeinflussen werden, glaube ich, ein nicht

[self.tableView beginUpdates]; 
[self.tableView endUpdates]; 

als verwendet verwenden sollten, wenn Sie führen insert, update or delete Operation auf Tableview und Sie kennen seine indexPath.

Verwenden Sie besser [self.tableView reloadData];, da nur sichtbare Zeilen oder Abschnitte in der Tabellenansicht aktualisiert werden. Beziehen Sie auch Apples Beispielcode für Table Search with UISearchController, es wird auch empfohlen, reloadData zu verwenden.

Nehmen Sie entsprechende Änderungen vor und Sie sind gut zu gehen.

Happy coding :)

+0

Ich bin mir bewusst, dass die Verwendung von 'reloadData' das Problem verschwinden lässt, obwohl das nicht erklärt, warum man' beginUpdates' und 'endUpdates' nicht verwenden kann. –

+0

@ Håvard das ist, was ich erklärt habe, wann 'beginUpdates und endUpdates' und' reloadData' zu verwenden sind. –

Verwandte Themen