UIPinchGestureRecognizer在UIRotationGestureRecognizer后失效问题排查
解决UIRotationGestureRecognizer和UIPinchGestureRecognizer先后触发的问题
这种手势互斥的问题我之前也碰到过,核心原因是iOS默认的手势识别逻辑会阻止某些手势在另一个手势之后触发,尤其是当两个手势都绑定在同一个视图上时。咱们一步步来解决:
第一步:设置手势代理并允许同时识别
首先,你需要让承载手势的控制器(或视图)遵守UIGestureRecognizerDelegate协议,给两个手势都设置delegate,再实现允许手势兼容的代理方法——这个方法会告诉系统:“这两个手势可以先后/同时被识别,不用互相阻塞”。
代码示例
先在你的控制器类扩展里声明协议:
@interface YourViewController () <UIGestureRecognizerDelegate> @property (nonatomic, strong) UIRotationGestureRecognizer *rotationGesture; @property (nonatomic, strong) UIPinchGestureRecognizer *pinchGesture; @property (nonatomic, weak) UIView *targetView; // 你要操作的目标视图 @end
初始化手势时记得设置delegate:
- (void)viewDidLoad { [super viewDidLoad]; // 初始化目标视图(替换成你自己的视图) self.targetView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 200, 200)]; self.targetView.backgroundColor = [UIColor orangeColor]; [self.view addSubview:self.targetView]; // 旋转手势 self.rotationGesture = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(handleRotation:)]; self.rotationGesture.delegate = self; [self.targetView addGestureRecognizer:self.rotationGesture]; // 捏合手势 self.pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinch:)]; self.pinchGesture.delegate = self; [self.targetView addGestureRecognizer:self.pinchGesture]; }
接着实现关键的代理方法:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { // 仅让我们的旋转和捏合手势互相兼容,避免影响其他手势 if ((gestureRecognizer == self.rotationGesture && otherGestureRecognizer == self.pinchGesture) || (gestureRecognizer == self.pinchGesture && otherGestureRecognizer == self.rotationGesture)) { return YES; } return NO; }
第二步:正确处理手势的增量变化
另外,在处理手势时,记得每次更新视图transform后重置手势的rotation和scale属性,这样每次手势的变化都是基于当前视图状态的增量,避免累积错误,也能让手势识别更流畅:
- (void)handleRotation:(UIRotationGestureRecognizer *)gesture { if (gesture.state == UIGestureRecognizerStateChanged) { // 应用旋转增量 self.targetView.transform = CGAffineTransformRotate(self.targetView.transform, gesture.rotation); gesture.rotation = 0; // 重置旋转量,下一次变化是新的增量 } } - (void)handlePinch:(UIPinchGestureRecognizer *)gesture { if (gesture.state == UIGestureRecognizerStateChanged) { // 应用缩放量 self.targetView.transform = CGAffineTransformScale(self.targetView.transform, gesture.scale, gesture.scale); gesture.scale = 1.0; // 重置缩放量,下一次变化是新的增量 } }
为什么之前会出问题?
iOS的手势识别器默认有互斥逻辑,当一个手势(比如旋转)开始识别并处理后,系统可能会标记该视图的触摸事件被“占用”,导致后续的捏合手势无法触发。通过实现shouldRecognizeSimultaneouslyWithGestureRecognizer:返回YES,就打破了这个互斥限制,让两个手势可以正常先后触发。
内容的提问来源于stack exchange,提问作者Arda Oğul Üçpınar
相关产品推荐
相关产品推荐

