简体   繁体   中英

Reactivecocoa two-way binding of UISlider to a value, update UI only when user isn't touching it

I have a UISlider which shows playback progress through a song and allows seeking within the song. Using RAC it's very easy to obtain a two-way binding between a UISlider's value and a viewModel's value:

RACChannelTo(self, slider.value) = RACChannelTo(viewModel, progress);

However problems arise while the user is interacting with the slider:

  • with continuous updates, while the user is moving the slider updates are constantly being sent to the VM leading to jittery sound;
  • without continuous updates, the jittery sound issue is no more, but the VM is constantly updating its progress value leading to the UI jumping to the latest value from under the user's finger.

I've tried the [slider rac_newValueChannelWithNilValue:@0] approach with same results. My current solution works, but is shamefully complex:

// Sadly the rac_signalForControlEvents doesn't send the event that triggered it so two signals are needed
RACSignal *touchDown = [self.slider rac_signalForControlEvents:UIControlEventTouchDown];
RACSignal *touchUp = [self.slider rac_signalForControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside];
RACSignal *isTouched = [[[touchDown map:^id(id value) {
  return @(YES);
}] merge:[touchUp map:^id(id value) {
  return @(NO);
}]] startWith:@(NO)]; // Needs a startWith because combineLatestWith doesn't send signals until it has at least one value from each component

[[RACObserve(viewModel, progress) combineLatestWith:isTouched] subscribeNext:^(RACTuple *tuple) {
  RACTupleUnpack(NSNumber * progress, NSNumber * isTouched) = tuple;
  // Update the slider value only if the user isn't touching it
  if (!isTouched.boolValue) {
      weakSelf.slider.value = progress.floatValue;
  }
}];
// Send the value only when user stops interacting
[[touchUp map:^id(UISlider *slider) {
  return @(slider.value);
}] subscribeNext:^(id x) {
  weakSelf.viewModel.progress = [x floatValue];
}];

Is there a better way of achieving this?

您是否尝试过使用throttle来减少从滑块发送的值的数量?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM