CKComponentViewAttributeValue CKComponentGestureAttributeInternal()

in ComponentKit/Core/Action/CKComponentGestureActions.mm [39:105]


CKComponentViewAttributeValue CKComponentGestureAttributeInternal(Class gestureRecognizerClass,
                                                                  CKComponentGestureRecognizerSetupFunction setupFunction,
                                                                  CKAction<UIGestureRecognizer *> action,
                                                                  const std::string& identifierSuffix,
                                                                  void (^applicatorBlock)(UIView *, UIGestureRecognizer *),
                                                                  void (^unapplicatorBlock)(UIGestureRecognizer *))
{
  if (!action || gestureRecognizerClass == Nil) {
    return {
      {
        std::string(class_getName(gestureRecognizerClass)) + "-"
        + CKStringFromPointer((const void *)setupFunction) + "-no-op",
        ^(UIView *view, id value) {}, ^(UIView *view, id value) {}
      },
      @YES  // Bogus value, we don't use it.
    };
  }

  auto reusePool = CKCreateOrGetReusePool(gestureRecognizerClass, setupFunction);
  CKAction<UIGestureRecognizer *> blockAction = action;
  return {
    {
      std::string(class_getName(gestureRecognizerClass))
      + "-" + CKStringFromPointer((const void *)setupFunction)
      + "-" + action.identifier()
      + identifierSuffix,
      ^(UIView *view, id value){
        RCCAssertNil(CKRecognizerForAction(view, blockAction),
                     @"Registered two gesture recognizers with the same action %@", NSStringFromSelector(blockAction.selector()));
        UIGestureRecognizer *gestureRecognizer = reusePool->get();
        CKSetComponentActionForGestureRecognizer(gestureRecognizer, blockAction);

        if (applicatorBlock != nil) {
          applicatorBlock(view, gestureRecognizer);
        }

        @try {
          [view addGestureRecognizer:gestureRecognizer];
        }
        @catch (NSException *ex) {
          CKComponent *mountedComponent = CKMountedComponentForView(view);
          NSString *fatalMsg = @"View does not have a mountedComponent";
          if (mountedComponent) {
            fatalMsg = [mountedComponent backtraceStackDescription];
          }
          CKCFatalWithCategory(mountedComponent.className, @"%@ while mounting \n%@", ex, fatalMsg);
        }
      },
      ^(UIView *view, id value){
        UIGestureRecognizer *recognizer = CKRecognizerForAction(view, blockAction);
        if (recognizer == nil) {
          return;
        }

        [view removeGestureRecognizer:recognizer];
        CKUnsetComponentActionForGestureRecognizer(recognizer);

        if (unapplicatorBlock != nil) {
          unapplicatorBlock(recognizer);
        }

        reusePool->recycle(recognizer);
      }
    },
    @YES // Bogus value, we don't use it.
  };
}