Reputation: 5828
I'm trying to implement a table view which should display cells according to the value of a UISlider.
Example: The table is empty. The user quickly drags the slider up to a value of 400. Now the table should contain 400 rows.
The data the cells should show is stored in core data and has about 400 entries. We're trying to achieve a cool effect when dragging the slider, so you can visually see each cell being added (if you're viewing the part of the table view where the cell would end up, of course). The built in animations supplied when using - (void) reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation
are sufficient, and the effect looks cool when going between 1 to 10 rows.
The problem: After the value has reached 10 or more it starts to lag too much to work. I think it's because reloadSections: has to check every cell every time the slider changes value and I loose too much precious time.
So, I'm looking for ideas on how to implement this. Should I use an NSFetchedResultsController and change the fetch request every time the slider changes value (which could happen 20 times per second)? Should I have all the data loaded into an array and just reuse cells the standard way?
I've tried both ways and the lag is pretty much the same. I'm thinking the problem might be that reloadSection: is too slow. I'm thinking that - (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
would be a better choice, but I'm looking for more ideas on how to implement this.
Any help would be appreciated!
The last code I tested when the slider changes value:
- (IBAction) sliderChangedValue:(UISlider *)slider
{
// Make sure we only run this function on integer changes. It fires too often on float changes.
if ((int)slider.value == lastSliderIntegerValue) {
return;
}
if (slider.value > lastSliderIntegerValue) {
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:(int)slider.value inSection:0]]
withRowAnimation:UITableViewRowAnimationAutomatic];
}
else {
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:(int)slider.value inSection:0]]
withRowAnimation:UITableViewRowAnimationAutomatic];
}
lastSliderIntegerValue = (int)slider.value;
Upvotes: 3
Views: 445
Reputation: 6803
I'm not incredibly experienced with iOS development, but I have done a lot of game dev. It seems like the root of your problem is the amount of animation that your program has to render. Since you said that your motivation for this program is preserving the cool effect, then you should change everything possible to optimize your program up to the point the user can perceive. I understand that isn't very clear, so here's a possible solution:
You shouldn't be animating the addition of every single row for every speed at which the user can move the slider. Instead, only animate as many as you need to for the experience to be smooth. This can be accomplished by calculating the rate at which the slider is being changed, and then adjusting how many rows are added to the table before reloadData is called. Only animate the addition of the last row in the cycle.
Because I don't know what system you're developing for or really much at all about the graphical power of the various iOS platforms, I can't really give you specific values, but you should play around with different settings and see what works.
Upvotes: 2