I have implemented an UITableView
with load more functionality. The tableView loads big images from a sometimes slow server. I'm starting an URLConnection for each image and reload the indexPath corresponding to the URLConnection (saved with the connection object). The connections themselves call -reloadData
on the tableView.
Now when clicking the load more button, I scroll to the first row of the new data set with position bottom. This works great and also my asynchronous loading system.
I faced the following issue: When the connection is "too fast", the tableView is reloading the data at a given indexPath while the tableView is still scrolling to the first cell of the new data set, the tableView scrolls back half the height of that cell.
This is what it should look like and what it actually does:
^^^^^^^^^^^^ should ^^^^^^^^^^^^ ^^^^^^^^^^^^^ does ^^^^^^^^^^^^^
And here is some code:
[[self tableView] beginUpdates];
for (NSMutableDictionary *post in object) {
[_dataSource addObject:post];
[[self tableView] insertRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:[_dataSource indexOfObject:post] inSection:0]] withRowAnimation:UITableViewRowAnimationBottom];
}
[[self tableView] endUpdates];
[[self tableView] scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:[_dataSource indexOfObject:[object firstObject]] inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
-tableView:cellForRowAtIndexPath:
starts a JWURLConnection if the object in the data source array is a string, and replaces it with an instance of UIImage
in the completion block. Then it reloads the given cell:
id image = [post objectForKey:@"thumbnail_image"];
if ([image isKindOfClass:[NSString class]]) {
JWURLConnection *connection = [JWURLConnection connectionWithGETRequestToURL:[NSURL URLWithString:image] delegate:nil startImmediately:NO];
[connection setFinished:^(NSData *data, NSStringEncoding encoding) {
[post setObject:[UIImage imageWithData:data] forKey:@"thumbnail_image"];
[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}];
[cell startLoading];
[connection start];
}
else if ([image isKindOfClass:[UIImage class]]) {
[cell stopLoading];
[cell setImage:image];
}
else {
[cell setImage:nil];
}
Can I prevent the tableView from performing the -reloadRowsAtIndexPaths:withRowAnimation:
calls until the tableView scrolling is done? Or can you imagine a good way to prevent this behavior?