djax djax - 6 months ago 32
Objective-C Question

Significant lag using UISlider when custom refresh is called

A UISlider is easily embedded in a tableview cell, however, a significant amount of lag seems to "build up" as you move the UISlider around and interact with a custom tableview reloading method that I call when the UISlider value changes.

Whenever the UISlider is moved around, a method is called that updates a label in the UITableview (The label is in the same UITableViewCell as the UISlider).

That method is added to the UISlider via:

[discoveryCell.radiusSlider addTarget:self
action:@selector(radiusSliderChanged:)
forControlEvents:UIControlEventValueChanged];


Here is the code for the update. (I didn't just call to reload the UITableview, since I want to prevent the tableview from scrolling to the top upon reload).

The logic behind the NSInteger "PREV_VALUE" simply exists to prevent excessive tableview reloading.

Code called when UISlider is moved:

CGFloat PREV_VALUE=-1;
-(void)radiusSliderChanged:(UISlider * )sender {

if (PREV_VALUE==-1) {
PREV_VALUE=sender.value;
return;
}

CGFloat currentValue=sender.value;

if (fabs(PREV_VALUE-currentValue)>.01) {
CGPoint contentOffset = self.tableView.contentOffset; //prevent tableview from scrolling
[self.tableView reloadData];
[self.tableView layoutIfNeeded];
[self.tableView setContentOffset:contentOffset];
PREV_VALUE=currentValue;

}



}


How do I avoid the resulting UISlider lag that seems to "build up"? Note that if I don't reload the tableview, I don't have the problem, but the label doesn't get updated.

The closest to a solution I've come is to set:

self.tableview.scrollsToTop=NO,


And then in radius changed just call:

[tableview reloadData]


But that gives one initial jumpy jitter UI thing.

Answer

Per rmaddy's suggestion you should change

[discoveryCell.radiusSlider addTarget:self
                                   action:@selector(radiusSliderChanged:)
                                          forControlEvents:UIControlEventValueChanged];

to

[discoveryCell.radiusSlider addTarget:self
                                   action:@selector(radiusSliderChanged:)
                                          forControlEvents: UIControlEventEditingDidEnd];

So that the table is reloaded only after the user has finished setting the radius. Right now it is reloaded multiple times as the slider is dragged around.

Also iOS is not a language it's an operating system and an SDK. Objective-C is the language.

If you have a label in the cell that you want to update continuously you can say something like:

[discoveryCell.radiusSlider addTarget:self
                                       action:@selector(updateRadiusLabel:)
                                              forControlEvents:UIControlEventValueChanged];

Then add an updateRadiusLabel: method:

- (void)updateRadiusLabel:(UISlider *)sender
{
    CGPoint location = [self.tableView convertPoint:sender.bounds.origin fromView:sender];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];
    MyTableViewCellSubclass *cell = [self.tableView cellForRowAtIndexPath];
    cell.label.text = [NSString stringWithFormate:@"%d",sender.value];
}
Comments