Search code examples
iphoneiostimeuislidercore-bluetooth

How can I control UISlider Value Changed-events frequency?


I'm writing an iPhone app that is using two uisliders to control values that are sent using coreBluetooth. If I move the sliders quickly one value freezes at the receiver, presumably because the Value Changed events trigger so often that the write-commands stack up and eventually get thrown away. How can I make sure the events don't trigger too often?

Edit:

Here is a clarification of the problem; the bluetooth connection sends commands every 105ms. If the user generates a bunch of events during that time they seem to que up. I would like to throw away any values generated between the connection events and just send one every 105ms.

This is basically what I'm doing right now:

-(IBAction) sliderChanged:(UISlider *)sender{

  static int8_t value = 0;
  int8_t new_value = (int8_t)sender.value;

  if ( new_value > value + threshold || new_value < value - threshold ) {
    value = new_value;  
    [btDevice writeValue:value];
  }
}

What I'm asking is how to implement something like

-(IBAction) sliderChanged:(UISlider *)sender{

  static int8_t value = 0;

  if (105msHasPassed) {
    int8_t new_value = (int8_t)sender.value;

    if ( new_value > value + threshold || new_value < value - threshold ) {
      value = new_value;  
      [btDevice writeValue:value];
    }
  }
}

Solution

  • I guess that it does make sense to still triggered them... What I would do in your case, would be to check the delta between the current value and the previous value. For instance:

    • Current value -> 5.
    • Next value -> 6.
    • Delta 1

    Just a bit of pseudo-code:

    if(delta>5){
     //do your stuff
    }
    

    I wouldn't probably do this but:

    -(void)sliderValueChanged:(UISlider *)sender{
        [self performSelector:@selector(removeAction:) withObject:sender afterDelay:0.3];
        // Do your stuff
    }
    
    - (void)removeAction:(UISlider *)sender{
        [sender removeTarget:self action:@selector(sliderValueChanged:) forControlEvents:UIControlEventValueChanged];    
    
        [self performSelector:@selector(addAction:) withObject:sender afterDelay:0.3];
    }
    
    - (void)addAction:(UISlider *)sender{
        [mySlider addTarget:self action:@selector(sliderValueChanged:) forControlEvents:UIControlEventValueChanged];   
    }
    

    I didn't tested this, but I think you get the idea.