UITapGestureRecognizer Programmatically trigger a tap in my view

前端 未结 8 1066
耶瑟儿~
耶瑟儿~ 2020-12-09 10:05

Edit: Updated to make question more obvious

Edit 2: Made question more accurate to my real-world problem. I\'m actually looking to take a

8条回答
  •  时光说笑
    2020-12-09 10:20

    I was facing the same issue, trying to simulate a tap on a table cell to automate a test for a view controller which handles tapping on a table.

    The controller has a private UITapGestureRecognizer created as below:

    gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
      action:@selector(didRecognizeTapOnTableView)];
    

    The unit test should simulate a touch so that the gestureRecognizer would trigger the action as it was originated from the user interaction.

    None of the proposed solutions worked in this scenario, so I solved it decorating UITapGestureRecognizer, faking the exact methods called by the controller. So I added a "performTap" method that call the action in a way the controller itself is unaware of where the action is originated from. This way, I could make a test unit for the controller independent of the gesture recognizer, just of the action triggered.

    This is my category, hope it helps someone.

    CGPoint mockTappedPoint;
    UIView *mockTappedView = nil;
    id mockTarget = nil;
    SEL mockAction;
    
    @implementation UITapGestureRecognizer (MockedGesture)
    -(id)initWithTarget:(id)target action:(SEL)action {
        mockTarget = target;
        mockAction =  action;
        return [super initWithTarget:target action:action];
        // code above calls UIGestureRecognizer init..., but it doesn't matters
    }
    -(UIView *)view {
        return mockTappedView;
    }
    -(CGPoint)locationInView:(UIView *)view {
        return [view convertPoint:mockTappedPoint fromView:mockTappedView];
    }
    -(UIGestureRecognizerState)state {
        return UIGestureRecognizerStateEnded;
    }
    -(void)performTapWithView:(UIView *)view andPoint:(CGPoint)point {
        mockTappedView = view;
        mockTappedPoint = point;
        [mockTarget performSelector:mockAction];
    }
    
    @end
    

提交回复
热议问题