2012-09-20 2 views
17

Heute Morgen habe ich die iOS 6.iOS UITableView scrollToRowAtIndexPath nicht mehr funktioniert

ich eine Tabellenansicht mit einer plist-Datei Kapitel und Linien geladen enthält nur neue Xcode installiert enthält. Kapitel definieren die Abschnitte.

Der Benutzer wählt Kapitel und Zeile aus und die Tabellenansicht wird automatisch zur richtigen Position (in der viewDidLoad) gescrollt.

NSIndexPath *indexPath = [NSIndexPath indexPathForRow:linePos inSection:chapterPos]; 
[self.tableView scrollToRowAtIndexPath:indexPath 
    atScrollPosition:UITableViewScrollPositionTop animated:YES]; 

das funktioniert einfach toll in iOS5 Simulator.

Wenn Sie dies im iOS 6-Simulator versuchen, wird der Bildlauf nicht ausgeführt. Ich bekomme keine Fehler. Ich habe überprüft, linePos und chapterPos erhalten korrekte Werte, aber der Bildlauf wird nicht durchgeführt.

Irgendwelche Ideen warum?

+4

nur um Schmerz und Elend hinzuzufügen ist es wieder 5 Jahre später in iOS 11 gebrochen. –

Antwort

26

Für aktuelle Versionen von iOS lesen Sie bitte die Antwort von Fjodor Volchyok. Beachten Sie, dass es nicht als die akzeptierte Antwort markiert ist, nur weil zum Zeitpunkt, zu dem die Frage zum ersten Mal gestellt wurde (Sept. 2012), die aktuelle Antwort die Arbeitslösung war. Neuere Versionen von iOS haben auch das gleiche Problem, das jetzt von Fjodor Volchyoks Antwort gelöst wird, also solltest du seine Antwort in diesem Moment +1 geben.


Ich fand die Antwort. Ich muß zuerst die Daten in dem

NSIndexPath *indexPath = [NSIndexPath indexPathForRow:linePos inSection:chapterPos]; 

[self.tableView reloadData]; 

[self.tableView scrollToRowAtIndexPath:indexPath 
    atScrollPosition:UITableViewScrollPositionTop animated:YES]; 
Tableview nachladen

Auch wenn ich die Antwort gefunden, weiß ich nicht, warum es in iOS5 und nicht in iOS6 arbeiten.

EDIT

Vielleicht soll ich das noch hinzufügen, wenn es funktioniert, war ich noch in der Anzeige die letzte Zeile ein Problem mit und veröffentlichte eine Frage für den

UItableview scrollToRowAtIndexPath not displaying last row correctly

Als @ Raj hat auch darum gebeten, ich sollte sagen, dass ich das in der viewDidLoad ausgelöst habe. Um das Problem zu beheben, dass die letzte Zeile nicht richtig angezeigt wurde, musste ich sie in die viewDidAppear setzen.

+0

Danke für diese Info, ich lief einfach in die gleiche Sache. Mir ist auch aufgefallen, dass das Scrolling der Tabelle nicht animiert wird, sondern nur in der ausgewählten Zeile angezeigt wird. –

+0

Triffst du den Aufruf scrollToRowAtIndexPath in deiner -viewDidLoad-Methode? –

40

Objective-C

[self.tableView reloadData]; 
dispatch_async(dispatch_get_main_queue(), ^{ 
     NSIndexPath *rowIndexPath = [NSIndexPath indexPathForRow:3 inSection:0]; 
     [self.tableView scrollToRowAtIndexPath:rowIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES]; 
}); 

Swift

tableView.reloadData() 
DispatchQueue.main.async { 
    let indexPath = IndexPath(row: linePos, section: chapterPos) 
    self.tableView.scrollToRow(at: indexPath, at: .top, animated: true) 
} 
+0

Es ist ein wichtiger Fix, ohne den die App je nach reloadData-Prozessen versehentlich abstürzen könnte. – BootMaker

+3

das ist das einzige, was für mich funktioniert (iOS 9.1). Der 'scrollToRowAtIndexPath' konnte immer nicht bis zur untersten Zelle scrollen, wenn ich ihn nicht in 'dispatch_async (dispatch_get_main_queue(), {...}' eingeschlossen hatte, obwohl' scrollToRowAtIndexPath 'bereits vom Hauptthread aufgerufen wurde. –

+0

Dies ist wahrscheinlich die richtige Antwort , PLUS legte dies in der viewDidAppear: –

1

Nach iOS7 Eigentum automaticallyAdjustsScrollViewInsets von UIViewController Standard YES ist. Dies führt dazu, dass das System die contentOffset von tableView anpasst, wenn der View-Controller gedrückt wird. Auch Sie rufen [self.tableView scrollToRowAtIndexPath:rowIndexPath atScrollPosition:UITableViewScrollPositionNone animated:NO]; in der viewWillAppear. Die contentOffset wird ebenfalls vom System nach viewWillAppear geändert. Also meine Lösung ist:

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    self.automaticallyAdjustsScrollViewInsets = NO; 

    /// any other codes 
} 

- (void)viewWillLayoutSubviews { 
    self.tableView.contentInset = UIEdgeInsetsMake(self.topLayoutGuide.length, 0, 0, 0); 
} 

- (void)viewWillAppear:(BOOL)animated { 
    [super viewWillAppear:animated]; 

    // change tableView data source 

    [self.tableView reloadData]; 
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[self.dataSourceArray count] - 1 inSection:0]; 
    [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionNone animated:NO]; 
} 
0

Ich füge diese Antwort als Ergänzung zu Fyodor Volchyoks Antwort hinzu. Ich habe auch festgestellt, dass das Dispatching das Problem löst. Ich konnte einen Workaround finden, der nicht versendet wird.

self.tableView.reloadData() 
let index = // the desired index path 

// For some reason, requesting the cell prior to 
// scrolling was enough to workaround the issue. 
self.tableView.cellForRowAtIndexPath(index) 

self.tableView.scrollToRowAtIndexPath(index, atScrollPosition: .Top, animated: false) 
+0

Ich hatte ein Problem mit Multithreading: wenn ich den Versand benutze, fängt eine meiner Methoden an, zweimal anzurufen und jetzt funktioniert es wie Magie !!! :-) –

0

Fyodor Volchyok Antwort in Swift:

tableView.reloadData() 
let indexPath = NSIndexPath(forRow: linePos, inSection: chapterPos) 
// make sure the scroll is done after data reload was finished 
dispatch_async(dispatch_get_main_queue()) { 
    self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Top, animated: true) 
} 
0

Es funktionierte für mich in ios11

self.tableView.estimatedRowHeight = 0; 
self.tableView.estimatedSectionFooterHeight = 0; 
self.tableView.estimatedSectionHeaderHeight = 0 

dispatch_async(dispatch_get_main_queue(), ^{ 
    NSInteger numberOfSections = self.tableView.numberOfSections; 
    if (numberOfSections > 0) 
    { 
    NSInteger lastSection = numberOfSections - 1; 
    NSInteger lastRowInLastSections = [self.tableView numberOfRowsInSection:lastSection] - 1; 

    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:lastRowInLastSections inSection:lastSection]; 
    [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:isAnimated]; 
} 
}); 
1

ich in ein anderes Problem lief (wahrscheinlich ein Fehler) mit scrollToRowAtIndexPath speziell auf einem iPhone X Ausführen von ios11. Mein Tisch hat ein paar hundert Abschnitte und im zusammengeklappten Modus würde ~ 10 in den sichtbaren Bildschirm passen. Als der IndexPath tiefer wurde, fiel das Scrollen allmählich zurück.

Zum Beispiel, wenn ich wollte, dass die Suche das Element in Zeile 30 findet, würde der ScrollPositionTop eine zusätzliche Zeile vor der eigentlichen Zeile haben, von der ich erwarte, dass sie oben ist.

Und als ich auf der Suche nach tieferen Reihen testete, fing es an, noch mehr hinter zu fallen, wo für irgendetwas über 100 Reihen tief oder so sagen, die erwartete Reihe kam nicht einmal im sichtbaren Bereich.

Die Workaround, die ich bisher gefunden habe, ist animiert zu sagen: NEIN für das Scrollen innerhalb von dispatch_async, dann funktioniert es ohne Störungen.