问题
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];
}
}
}
回答1:
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.
回答2:
You could get complicated and filter the input from the slider based on either some timestamp or whether the difference between the new value and the old value is greater than some threshold.
A simpler way would be to just use a different event: touchEnded. That way you are only sending a final value and not all the intermediate values.
May not be appropriate for your app but it is not entirely clear what you are needing to do.
回答3:
Just an idea, but what you could do is not send in the value changed event. You could store the value of the last transmission in a variable, then you could have a timer running in the background that checks if the last value sent is different to the current slider value, if it is then send the new value. The timer could be set to fire every 105ms and it will only send value every 105ms if the new value is different to the last sent value.
来源:https://stackoverflow.com/questions/11324359/how-can-i-control-uislider-value-changed-events-frequency