为啥 touchesbegan:在使用 UIPinchGestureRecognizer 后从不会在 UIView 上被调用?

Posted

技术标签:

【中文标题】为啥 touchesbegan:在使用 UIPinchGestureRecognizer 后从不会在 UIView 上被调用?【英文标题】:Why touchesbegan: never gets called on a UIView after UIPinchGestureRecognizer is used?为什么 touchesbegan:在使用 UIPinchGestureRecognizer 后从不会在 UIView 上被调用? 【发布时间】:2016-08-22 12:32:20 【问题描述】:

我正在开发一个绘图应用程序,它允许用户在其 superView (self.view) 子视图的 UIView (InsideView) 上绘制 UIbezierpath。我在 InsideView 中使用传统的绘图代码,例如 touchesBegan:, touchesMoved:, touchesEnded:,我在 viewController 类(这是 InsideView 的 superView)中处理捏缩放代码 handlePinch:(UIPinchGestureRecognizer *)recognizer:

当我第一次绘制时,我可以在它之后进行缩放缩放,但是当我首先进行缩放缩放时,在触发 UIPinchGestureRecognizer 并且它不会在 InsideView 上绘制任何内容后,不会调用绘制代码(touchesBegan 等)。我究竟做错了什么?提前致谢。

//InsideView中的代码(是UIView的子类,是self.view的子视图)

- (id)initWithFrame:(CGRect)frame              
                 self = [super initWithFrame:frame];
                 if (self) 
                             path = [UIBezierPath bezierPath];
                             [path setLineWidth:7.0];
                             pointsArray = [NSMutableArray array];
                             finish = NO;
                             
                   return self;   
   
-(void)drawRect:(CGRect)rect
                        [[UIColor redColor] setStroke];
                        [path stroke];

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

                    UITouch *touch = [touches anyObject];
                    CGPoint p = [touch locationInView:self];
                    [path moveToPoint:p];
                    [pointsArray addObject:[NSValue valueWithCGPoint:p]];

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event

                    UITouch *touch = [touches anyObject];
                    CGPoint p = [touch locationInView:self];
                    [path addLineToPoint:p];
                    [self setNeedsDisplay];
                    [pointsArray addObject:[NSValue valueWithCGPoint:p]];

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event

                    [path closePath];

                    //Smoothing the path.
                    path.miterLimit=-10;
                    [self setNeedsDisplay];
                    finish = YES;


//Code in the viewController (InsideView's superView)
- (void)viewDidLoad 
        [super viewDidLoad];
        InsideView* sV = [InsideView new];
        [sV setFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
        [self.view addSubview:sV];

        //Pinch
        UIPinchGestureRecognizer*pinch = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(handlePinch:)];
        pinch.delegate =self;
        [sV addGestureRecognizer:pinch];

- (void)handlePinch:(UIPinchGestureRecognizer *)recognizer

        if ([recognizer numberOfTouches] < 2)
            return;
        if (recognizer.state == UIGestureRecognizerStateBegan) 
            lastScale = 1.0;
            lastPoint = [recognizer locationInView:self.view];
        
        // Scale
        CGFloat scale = 1.0 - (lastScale - recognizer.scale);
        [sV.layer setAffineTransform:
         CGAffineTransformScale([sV.layer affineTransform],
                                scale,
                                scale)];
        lastScale = recognizer.scale;
        // Translate
        CGPoint point = [recognizer locationInView:self.view];

        [sV.layer setAffineTransform:
         CGAffineTransformTranslate([sV.layer affineTransform],
                                    point.x - lastPoint.x,
                                    point.y - lastPoint.y)];
        lastPoint = [recognizer locationInView:self.view];

-(void)handlePinchWithGestureRecognizer:(UIPinchGestureRecognizer *)pinchGestureRecognizer
        sV.transform = CGAffineTransformScale(sV.transform, pinchGestureRecognizer.scale, pinchGestureRecognizer.scale);
        pinchGestureRecognizer.scale = 1.0;

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
        return YES;

【问题讨论】:

尝试在你的 touchesSomething 方法中调用 super。当您的手势识别器触发时,还将完成设置为 true(只是猜测......) 我建议您删除此代码行pinch.delegate = self;,因为它不是必需的,也许这可以解决您的问题 您可以尝试从 drawRect 中删除捏合手势设置并将其移动到 initWithFrame 以便它只发生一次吗?每次在drawRect上设置pinch也是荒谬的。 【参考方案1】:

我开发了一个 UIViewController,我将它们一起使用没有任何问题,也许解决方案是将这个逻辑从 UIView 移动到 UIViewController。所以在viewDidLoad你可以像这样定义捏识别器

UIPinchGestureRecognizer* pinch = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(handlePinch:)];
[self.view addGestureRecognizer:pinch];

当然handlePinch:方法也应该和touchesBegan:withEvent:一起移动到UIViewControllertouchesMoved:withEvent:, touchesEnded:withEvent: 方法

在这些方法中你应该改变的是你应该改变

self

self.yourSpecificCurrentUIView

【讨论】:

感谢您的建议,我在 ViewController 中提供了捏合处理代码,这是我的绘图视图的父视图,我在绘图视图(它是一个 uiview 子类)中提供了绘图代码。它确实解决了问题。

以上是关于为啥 touchesbegan:在使用 UIPinchGestureRecognizer 后从不会在 UIView 上被调用?的主要内容,如果未能解决你的问题,请参考以下文章

touchesBegan 在 uiresponder 的子类中被忽略

pressGestureRecognizer and touchesBegan

如何加速 touchesBegan 事件触发?

TouchesBegan 只调用了一次

仅对 touchesBegan 和 NOT 手势识别器使用 hitTest 逻辑

touchesBegan 在 PDFView 中没有触发