void CKPerformOptimisticViewMutation()

in ComponentKit/Core/CKOptimisticViewMutations.mm [27:94]


void CKPerformOptimisticViewMutation(UIView *view,
                                     CFTimeInterval persistTime,
                                     CKOptimisticViewMutationGetter getter,
                                     CKOptimisticViewMutationSetter setter,
                                     id value,
                                     id context)
{
  RCCAssertMainThread();
  RCCAssertNotNil(view, @"Must have a non-nil view");
  RCCAssertNotNil(getter, @"Must have a non-nil getter");
  RCCAssertNotNil(setter, @"Must have a non-nil setter");
  if (view == nil || getter == nil || setter == nil) {
    return;
  }

  if (CKReadGlobalConfig().useNewStyleOptimisticMutations) {
    __block int loadCount = 0;
    __block id oldValue = nil;
    __block CKOptimisticMutationToken token = CKOptimisticMutationTokenNull;

    auto undo = ^(UIView *v) {
      if (!RCObjectIsEqual(getter(v, context), oldValue)) {
        setter(v, oldValue, context);
        RCCAssert(RCObjectIsEqual(getter(v, context), oldValue), @"Setter failed to undo to old value");
      }
    };

    auto load = persistTime == 0 ?
      ^(UIView *v) {
        if (loadCount++ == 0) {
          oldValue = getter(view, context);
        } else {
          oldValue = getter(view, context);
          CK::Component::AttributeApplicator::removeOptimisticViewMutation(token);
          token = CKOptimisticMutationTokenNull;
        }
      } :
      ^(UIView *v) {
        oldValue = getter(view, context);
      };

    auto apply = ^(UIView *v) {
      if (!RCObjectIsEqual(getter(v, context), value)) {
        setter(v, value, context);
        RCCAssert(RCObjectIsEqual(getter(view, context), value), @"Setter failed to redo to new value");
      }
    };

    if (persistTime != 0) {
      const auto dispatchTime = dispatch_time(DISPATCH_TIME_NOW, int64_t(NSEC_PER_SEC * persistTime));

      dispatch_after(dispatchTime, dispatch_get_main_queue(), ^{
        CK::Component::AttributeApplicator::removeOptimisticViewMutation(token);
        token = CKOptimisticMutationTokenNull;
      });
    }

    token = CK::Component::AttributeApplicator::addOptimisticViewMutation(view, undo, apply, load);
  } else {
    id oldValue = getter(view, context);
    CK::Component::AttributeApplicator::addOptimisticViewMutationTeardown_Old(view, ^(UIView *v) {
      setter(v, oldValue, context);
      RCCAssert(RCObjectIsEqual(getter(v, context), oldValue), @"Setter failed to restore old value");
    });
    setter(view, value, context);
    RCCAssert(RCObjectIsEqual(getter(view, context), value), @"Setter failed to apply new value");
  }
}