Reputation: 3853
I have an app that has the ability to download certain files. These files are shown in a UITableView
, and when tapped, they begin to download.
I would like to show the progress of the downloads in the cell (for example, as a percentage). My code currently fires notifications when the download progress is updated.
The problem is that these progress updates are fired many (hundreds?) times per second. If I use [tableView reloadData]
, or even [tableView reloadRowsAtIndexPaths:...]
, the UI lags like crazy once the download starts, because this is being called so frequently.
My code is very minimal other than this. I'm not using any uncommon UITableView delegate methods, and I've tried to eliminate everything other than updating the 'download' label in cellForRowAtIndexPath:
- but it still lags a lot!
What are my options? I could potentially create a timer that updates the UI every second or so in order to show download progress, but this seems hacky. The UI could be so much better! Is there any way that I can have my download label update instantly without lagging my UI?
Upvotes: 1
Views: 1614
Reputation: 3675
It sounds like you need to slow down the flow of notifications.
Assuming progress is between 0 and 1, in the method that fires the notification, use something similar to:
if (floorf(progress*100) == progress*100) {
// send notification
}
This would only send a notification to refresh the cell when the progress if 1%, 2% etc.
In addition, in the UITableView, try to only reload visible cells:
if ([[self.tableView indexPathsForVisibleRows] containsObject:indexPath]) {
[self.tableView reloadRowsAtIndexPath:@[ indexPath ]];
}
Upvotes: 2
Reputation: 3981
I would use the performSelector:withObject:afterDelay method, which would look something like this
[self performSelector:@selector(updateCell:) withObject:cell afterDelay:0.5];
The updateCell method would look something like this
- (void)updateCell:(CustomUITableViewCell *)cell {
[cell setNeedsLayout];
if (cell && cell.downloadPercentage < 100) {
[self updateCell:cell];
}
}
What this is doing is calling the updateCell method every 1/2 second until the download is complete. It calls [cell setNeedsLayout] (or you could call whatever method you want to update your cell's display to update the percentage bar, like [cell setNeedsDisplay] or [cell updateDownloadLabel]) to update the cell, then calls updateCell again.
You can play around with the delay to get it looking and feeling how you want and balance performance.
There may be some issue with this getting called after a cell is scrolled off the screen, so make sure to check the cell still exists
Upvotes: 0