2014-08-31 10 views
9

Ich habe eine _TableView mit Elementen, und ich möchte automatische Aktualisierung einstellen, und ich möchte nicht, dass es bei Aktualisierung scrollen, sagen wir Benutzer scrollte 2 Seiten nach unten, und die Aktualisierung trigered -> so ich will den erneuerten Inhalt an die Spitze der Tabelle setzen, ohne Benutzer-interuptingUITableView Refresh ohne Bildlauf

Scrollen

Angenommen Benutzer waren auf Reihe 18 und jetzt wird die _dataSource aktualisiert, so dass es abgeholt 4 Artikel kann sagen, so mag ich Benutzer auf dem Punkt bleiben er war.

Was wäre der beste Ansatz, um es zu erreichen?

+0

hoffen, diese Antworten Ihnen helfen: http://stackoverflow.com/questions/5872759/uitableview-insert-rows-without-scrolling/11585557#11585557 – stosha

Antwort

9

Ich zeige, wenn nur eine Zeile hinzugefügt wird. Sie können es auf mehrere Zeilen erweitern.

// dataArray is your data Source object 
    [dataArray insertObject:name atIndex:0]; 
    CGPoint contentOffset = self.tableView.contentOffset; 
    contentOffset.y += [self tableView:self.tableView heightForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; 
    [self.tableView reloadData]; 
    [self.tableView setContentOffset:contentOffset]; 

Aber für diese Sie die Methode - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath definiert haben, müssen zu arbeiten. Oder Sie können die Tabellenansicht direkt angeben, wenn sie konstant ist.

+0

Es ist nicht konstant, und vielen Dank für Ihre Antwort, die ich werde es versuchen, – ColdSteel

+0

Ja dann haben Sie sicher die Methode von '- (CGFloat) definiert tableView: (UITableView *) tableView heightForRowAtIndexPath: (NSIndexPath *) indexPath'. Akzeptiere meine Antwort, wenn es dir geholfen hat. – user1190882

2

ich es auf diese Weise tun:

messages.insertContentsOf(incomingMsgs.reverse(), at: 0) 
table.reloadData() 

// This is for the first load, first 20 messages, scroll to bottom 
if (messages.count <= 20) { 
     let indexToScroll = NSIndexPath(forRow: saferSelf.messages.count - 1, inSection: 0) 
     table.scrollToRowAtIndexPath(indexToScroll, atScrollPosition: .Top , animated: false) 
} 
// This is to reload older messages on top of tableview 
else { 
     let indexToScroll = NSIndexPath(forRow: incomingMsgs.count, inSection: 0) 
     table.scrollToRowAtIndexPath(indexToScroll, atScrollPosition: .Top , animated: false) 
     // Remove the refreshControl.height + tableHeader.height from the offset so the content remain where it was before reload 
     let theRightOffset = CGPointMake(0, table.contentOffset.y - refreshControl.frame.height - table.headeView.frame.height) 
     table.setContentOffset(theRightOffset, animated: false) 
} 

... auch, da ich dynamische Zellenhöhe verwenden, einige Verrücktheit zu vermeiden, wird die Schätzung zwischengespeichert:

var heightAtIndexPath = [NSIndexPath: CGFloat]() 
func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { 
    return heightAtIndexPath[indexPath] ?? UITableViewAutomaticDimension 
} 
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { 
    heightAtIndexPath[indexPath] = cell.frame.height 
} 
12

Dies ist Fehler von iOS8 bei Verwendung von UITableViewAutomatic Dimension. Wir müssen den Inhalts-Offset der Tabelle speichern, die Tabelle neu laden, das Layout erzwingen und contenOffset zurück setzen.

CGPoint contentOffset = self.tableView.contentOffset; 
[self.tableView reloadData]; 
[self.tableView layoutIfNeeded]; 
[self.tableView setContentOffset:contentOffset]; 
+0

Diese erste Zeile über iOS 8 retten meinen Tag. – CRDave

16

Für Swift 3+:

Sie benötigen den Strom der UITableView Offset speichern und anschließend neu zu laden und dann die wieder auf den UITableView Offset eingestellt.

ich geschaffen habe, um diese Funktion zu diesem Zweck:

func reload(tableView: UITableView) { 

    let contentOffset = tableView.contentOffset 
    tableView.reloadData() 
    tableView.layoutIfNeeded() 
    tableView.setContentOffset(contentOffset, animated: false) 

} 

Rufen Sie einfach mit: reload(tableView: self.tableView)

+0

Was passiert, wenn die Tabellenansicht den Offset nicht ändert, lädt die neuen Zellen noch? –

+0

@RockBalbao - Ich verstehe deine Frage nicht bro –

+0

Ich benutze NSFetchedResultsControllerDelegate. Jetzt verwende ich UIRefreshControl, um alte Zellen in scrollDown zu laden. Bei performFetch werden die Daten geladen Ich muss nur Daten neu laden. aber ich möchte die neu geladenen Zellen nicht anzeigen. Lassen Sie sie oben laden. Wenn ich oben scrolle, werden nur sie sichtbar. Um dies zu implementieren, habe ich versucht, diese contentOffset-Methode zu verwenden. aber vor reloadData und nach reloadData ist der contentOffset gleich, obwohl er einige Zeilen über –

0

Versuch

zu ersetzen

reloadData mit

tableView.reloadRows (at: tableView!.indexPathsForVisibleRows!, with: .none),

aber Sie sollten sich um no cells kümmern, wenn no cells, sollte diese Methode Absturz verursachen.

0

Wenn Sie neu laden wollen Sie müssen

self.tableView.reloadData()

self.tableView.(LayoutIfNeeded)

und nutzen auch dieses UITableViewDelegate

func Tableview (_ Tableview: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { return 'Ihre maximale Zellenhöhe' }

und Ihre Tableview wird auf der vorherigen Bildlaufposition ohne Bildlauf bleiben

0

Dieser Code wird unnötige Animation verhindern und den Inhaltsversatz der Bildlaufansicht beibehalten, es funktionierte gut für mich.

let lastScrollOffset = tableView.contentOffset 
tableView.beginUpdates() 
tableView.reloadData() 
tableView.endUpdates() 
tableView.layer.removeAllAnimations() 
tableView.setContentOffset(lastScrollOffset, animated: false) 
Verwandte Themen