How can I tell when UITableView has completed ReloadData?
The reload happens during the next layout pass, which normally happens when you return control to the run loop (after, say, your button action or whatever returns).
So one way to run something after the table view reloads is simply to force the table view to perform layout immediately:
[self.tableView reloadData];
[self.tableView layoutIfNeeded];
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];
Another way is to schedule your after-layout code to run later using dispatch_async
:
[self.tableView reloadData];
dispatch_async(dispatch_get_main_queue(), ^{
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];
});
UPDATE
Upon further investigation, I find that the table view sends tableView:numberOfSections:
and tableView:numberOfRowsInSection:
to its data source before returning from reloadData
. If the delegate implements tableView:heightForRowAtIndexPath:
, the table view also sends that (for each row) before returning from reloadData
.
However, the table view does not send tableView:cellForRowAtIndexPath:
or tableView:headerViewForSection
until the layout phase, which happens by default when you return control to the run loop.
I also find that in a tiny test program, the code in your question properly scrolls to the bottom of the table view, without me doing anything special (like sending layoutIfNeeded
or using dispatch_async
).
How to detect the end of loading of UITableView
Improve to @RichX answer:lastRow
can be both [tableView numberOfRowsInSection: 0] - 1
or ((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject]).row
.
So the code will be:
-(void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if([indexPath row] == ((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject]).row){
//end of loading
//for example [activityIndicator stopAnimating];
}
}
UPDATE:
Well, @htafoya's comment is right. If you want this code to detect end of loading all data from source, it wouldn't, but that's not the original question. This code is for detecting when all cells that are meant to be visible are displayed. willDisplayCell:
used here for smoother UI (single cell usually displays fast after willDisplay:
call). You could also try it with tableView:didEndDisplayingCell:
.
Can I call a function when UITableView has finished loading?
Try this delegate method, when this is called, the text is already in the cell, and you can test for it and add or remove the accessory. From the docs:
Discussion
A table view sends this message to its delegate just before it uses cell to draw a row, thereby permitting the delegate to customize the cell object before it is displayed. This method gives the delegate a chance to override state-based properties set earlier by the table view, such as selection and background color. After the delegate returns, the table view sets only the alpha and frame properties, and then only when animating rows as they slide in or out.
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
// check text and do something
}
wait till UITableView finish reloadData
There is a very simple solution is to check if you are in the last iteration of the delegate
-(void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
after last iteration finished in the end add your code there
-(void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if([indexPath row] == lastRow){
any code you want
}
}
Thanks
How i know reloadData has finished
There isn't any method which will tell you that UITableView has finished loading all cells. A workaround is to check if indexPath.row is last item in your data set when you get this dataSource callback -
tableView(UITableView, cellForRowAt: IndexPath)
and then call loadingView() from within cellForRowAt: method.
How can I tell When a UITableView animation has finished?
[CATransaction begin];
[CATransaction setCompletionBlock: ^{
// your animation has finished
}];
[tableView setEditing:YES animated:YES];
[CATransaction commit];
Note that setCompletionBlock
must be on the top.
Why is data not displayed when viewDidLoad finished in swift?
Did you set the tableView.dataSource
to self
? Also, you need to call tableView.reloadData()
for populating the datas. Hope this helps.
Related Topics
How to Programmatically Connect to a Wifi Network Given the Ssid and Password
How to Make Drawrect Work Right Now
Correct Singleton Pattern Objective C (Ios)
How to Import Own Classes from Your Own Project into a Playground
Xcode 9 Gm - Wkwebview Nscoding Support Was Broken in Previous Versions
Cannot Install Alamofire in New Xcode Project. "No Such Module Alamofire"
Remove Objects with Duplicate Properties from Swift Array
Swift: Issue in Converting String to Double
Swiftui - How to Pass Environmentobject into View Model
What's the Best Way to Detect When the App Is Entering the Background For My View
How to Resize the Iphone/iPad Simulator
Why Uitableviewautomaticdimension Not Working
Adding Custom Fonts to iOS App Finding Their Real Names
Nsinternalinconsistencyexception', Reason: 'Could Not Load Nib in Bundle: 'Nsbundle
Enumerate All Keychain Items in My iOS Application
Modal Dialog Does Not Dismiss Keyboard
How to Programmatically Check Whether a Keyboard Is Present in iOS App