I currently have a set up where tapping a cell causes an activity indicator to come up on the cell while a network process is being done. Once it finishes, the cell automatically updates its UI.
The problem is, while this is going on, if a user scrolls the cell off the screen it currently gets reused and when you scroll back the cell is either in the pre-tapped UI, or the post-tapped UI (depending on whether process completed while user was scrolled away).
This makes it seem like the background action being done just stops randomly to a users perspective, but it is still happening, just the UI gets refreshed.
So I'm struggling with how to either temporarily prevent the reuse of the cell, or otherwise is there any way I can maintain a consistent loading indicator on a cell (and only on that cell) even after reuse?
EDIT: The idea of saving the indexPath
with some data to display from instead is a step in the right direction, but the ordering is likely, but not guaranteed to remain the same.
So I guess the problem becomes: I need to find something unique to identify a given cell with when I get the delegate call that the process is done. I attempted to use the label's text since it is "unique" (99% of the time...) but this only is guaranteed to work unless I also pass the "unique" identifier (the label, which isn't even guaranteed to be unique) on a fun roller coaster ride through my support classes just so it can be used at the VERY end.
Things I've Tried
1) Attempt: Retaining the cell by placing it in a NSMutableArray property while it was loading, and using a delegate method to remove it once it finished i.e.:
[self.loadingCells addObject:cell];
Result: No Effect
2) Attempt: Adding a property to the UITableViewCell (I subclassed) called isLoading
.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
...
if (cell.isLoading) {
[cell.activityView startAnimating];
}
}
Result: Loading indicator on correct cell, but also others when off screen.
Worked decently, but I ran into the issue of other random cells now mysteriously looking like they're loading because the original cell got reused to make them.
3) Attempt: Same as attempt #1, except using the (unique) cell's label's text:
[self.loadingCells addObject:cell.label.text];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
...
if ([self.loadingCells containsObject:cell.label.text]) {
[cell.activityView startAnimating];
}
}
// delegate method
- (void)finishedLoading:(MyCell *)cell {
[cell.activityView stopAnimating];
[self.loadingCells removeObject:cell.label.text];
}
Result: Loading indicator on correct cell only, but delegate method tries to remove wrong label's text if cell not on screen when process finishes, resulting in cell looking like its perpetually loading.
4) I then proceeded to ALSO pass an NSString on the delegate method and attempt to compare them and remove the correct string... This gave unreliable results as well. I presume that this is because the cell that gets passed along to the classes that handle the network calls may doesn't remain static and such if I happen to not be showing the cell when I make the call to extract the label's text it'll be incorrect.
So I COULD make the NSString right away and pass it along through the wonderful web of calls I make in different classes but this is just ridiculous and I was already disliking this solution...