Mai mult
Cum să-i spuneți atunci când UITableView a finalizat ReloadData?
Am încercat pentru a defila la partea de jos a unui UITableView după ce este făcut efectuarea [self.tableView reloadData]
Am avut inițial
[self.tableView reloadData]
NSIndexPath* indexPath = [NSIndexPath indexPathForRow: ([self.tableView numberOfRowsInSection:([self.tableView numberOfSections]-1)]-1) inSection: ([self.tableView numberOfSections]-1)];
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
Dar apoi am citit că reloadData este asincron, astfel încât defilare nu't se întâmple de la sine.tableView,
[self.tableView numberOfSections] " și " [self.tableView numberOfRowsinSection` sunt 0.
Multumesc!!!
Ce's ciudat este că eu sunt, folosind:
[self.tableView reloadData];
NSLog(@"Number of Sections %d", [self.tableView numberOfSections]);
NSLog(@"Number of Rows %d", [self.tableView numberOfRowsInSection:([self.tableView numberOfSections]-1)]-1);
In consola se întoarce Secțiunile = 1, Rand = -1;
Când m-am face exact același NSLogs în cellForRowAtIndexPath
am Secțiunile = 1 și rl = 8; (8 este dreapta)
166
17
Reload se întâmplă în următoarea layout trece, ceea ce se întâmplă în mod normal atunci când vă întoarceți de control pentru a rula în buclă (după, să zicem, butonul de acțiune sau ce se întoarce).
Deci, un mod de a rula ceva după masă vedere reîncarcă este pur și simplu pentru a forța tabelul de vedere pentru a efectua aspectul imediat:
O altă modalitate este de la programul de după-layout cod pentru a rula mai târziu, folosind
dispatch_async
:UPDATE
După mai multe investigații, am aflat că cei de tabel trimite tableView:numberOfSections: "și" tableView:numberOfRowsInSection:
la sursa de date înainte de a reveni la reloadData
. Dacă delegatul implementeazătableView:heightForRowAtIndexPath:
, tabelul de vedere, de asemenea, trimite asta (pentru fiecare rând) înainte de a reveni la reloadData`.Cu toate acestea, tabelul de vedere nu trimite `tableView:cellForRowAtIndexPath: "sau" tableView:headerViewForSection până la aspect de fază, care se întâmplă în mod implicit atunci când vă întoarceți de control pentru a rula în buclă.
Am găsi, de asemenea, că într-un mic program de testare, codul în întrebarea dumneavoastră în mod corespunzător se va derula la partea de jos a tabelului vedere, fără ca eu sa fac nimic special (cum ar fi trimiterea de
layoutIfNeeded
sau folosinddispatch_async
).Swift:
Obiectiv-C:
Ca de Xcode 8.2.1, iOS 10, și swift 3,
Puteți determina sfârșitul lui
tableView.reloadData()
cu ușurință prin utilizarea unui CATransaction bloc:Cele de mai sus, de asemenea, funcționează pentru a determina sfârșitul perioadei de UICollectionView's reloadData() și UIPickerView's reloadAllComponents().
Anii
dispatch_async(dispatch_get_main_queue())
metoda de mai sus este nu este garantat de a lucra. Am'm a vedea non-deterministe comportament cu ea, în care, uneori, sistemul a finalizat layoutSubviews și celula de redare înainte de finalizarea bloc, și, uneori, după.Aici's o soluție care funcționează 100% pentru mine, pe iOS 10. Este nevoie de capacitatea de a instantia UITableView sau UICollectionView ca un obicei subclasă. Aici's UICollectionView soluție, dar's exact la fel pentru UITableView:
CustomCollectionView.h:
CustomCollectionView.m:
Exemplu de utilizare:
A se vedea aici pentru o Rapidă versiune de acest răspuns
Am avut aceleași probleme ca Tyler Sheaffer.
Am implementat solutia în Swift și-a rezolvat problemele mele.
Swift 3.0:
Swift 2:
Exemplu De Utilizare:
Se pare oamenii sunt încă lectură această întrebare și răspunsuri. B/c, am'm editarea răspunsul meu pentru a elimina cuvântul Sincron care este de fapt irelevant pentru acest lucru.
Când [tableView reloadData]
întoarce, structurile de date interne spatele tableView au fost actualizate. Prin urmare, atunci când metoda completează în condiții de siguranță puteți defila la partea de jos. Am verificat acest lucru în propria mea aplicație. Acceptate pe scară largă răspunde de @rob-mayoff, în timp ce, de asemenea, confuz în terminologie, recunoaște același în ultima actualizare.Dacă
tableView
e't defilare la partea de jos posibil să aveți o problemă în alt cod te-ai't postate. Poate că se schimbă datele după defilare este completă și te're nu reîncărcare și/sau defilare la partea de jos atunci?Adăuga unele de logare după cum urmează pentru a verifica dacă tabelul de date este corectă după reloadData`. Am codul de mai jos într-o mostră de aplicație și funcționează perfect.
Și o
UICollectionView
versiune, bazată pe kolaworld's răspuns:https://stackoverflow.com/a/43162226/1452758
Are nevoie de testare. Funcționează până în prezent pe iOS 9.2, Xcode 9.2 beta 2, cu o defilare collectionView la un indice, ca o închidere.
Utilizare:
Eu folosesc acest truc, destul de sigur că am postat deja la un duplicat al întrebarea asta:
De fapt asta mi-a rezolvat problema:
Încercați acest mod se va lucra
Eu va executa atunci când masa este complet încărcat
O altă Soluție este de a putea subclasa UITableView
Am încheiat cu o variație de Shawn's soluție:
Creați un obicei UITableView clasa cu un delegat:
Apoi, în codul meu, eu folosesc
De asemenea, asigurați-vă că setați masă vederea CustomTableView în interface builder:
În Swift 3.0 + putem crea o extensie pentru
UITableView", cu un " scăpat de Închidere
ca mai jos :Și să-l Utilizați ca mai Jos, în cazul în care vreodată doriți :
sper că acest lucru va ajuta pentru cineva. noroc!
Detalii
Soluție
Utilizare
Eșantion complet
Rezultate
Doar să oferim o altă abordare, bazată pe ideea de finalizare fiind 'ultima vizibil' mobil pentru a fi trimis la
cellForRow
.O posibila problema este: Dacă
reloadData()
a terminat înainte delastIndexPathToDisplay
a fost stabilit, 'ultima vizibil' mobil va fi afișat înainte delastIndexPathToDisplay
a fost stabilit și finalizarea nu va fi numit (și va fi în 'teptare' de stat):Dacă am inversa, ne-am putea trezi cu finalizare fiind declanșat de defilare înainte de
reloadData()
.Încercați acest lucru:
tableView.backgroundColor = .negru
tableView.reloadData()
DispatchQueue.principal.asincron(execută: {
})
// De tableView culoare va schimbat de la negru la verde numai după reloadData() funcția completă.
Îl puteți folosi pentru a face ceva după reîncărcare date:
Încercați setarea întârzieri: