iOS开发中为临时UIView添加向下滑动关闭手势无响应如何解决
手势无法触发的原因及解决方案
核心原因
- 属性拼写错误:你代码里写的
toastView.isUserInteractionAvailable = true是错误的,UIView开启用户交互的正确属性是isUserInteractionEnabled,写错属性导致toastView根本不接收任何触摸事件,手势自然无法触发。 - 动画默认禁用交互:UIKit的
UIView.animate方法默认会在动画执行过程中禁用视图的用户交互,你提前添加了延迟duration后执行的消失动画,在等待动画执行和动画运行的整个周期内,toastView的交互都被默认关闭了。 - 子视图拦截触摸:如果
AnimationView或者UILabel开启了用户交互,会优先吃掉触摸事件,不会传递给父视图的手势识别器。 - 自动消失动画未取消:就算手势触发了,未取消的预加消失动画也可能导致后续逻辑异常。
修复步骤
- 修正用户交互属性配置
把错误的交互属性替换为正确写法,同时关闭不需要交互的子视图的交互能力,避免触摸被拦截:
// 替换错误的isUserInteractionAvailable toastView.isUserInteractionEnabled = true // 子视图不需要交互就关闭,避免拦截 animationView.isUserInteractionEnabled = false messageLabel.isUserInteractionEnabled = false
- 给动画添加允许交互的参数
把原有自动消失的延迟动画改用DispatchWorkItem实现,方便手动取消,同时给所有动画添加.allowUserInteraction选项:
// 弹出动画 UIView.animate(withDuration: 0.2, delay: 0, options: .allowUserInteraction, animations: { toastView.frame.origin.y = self.view.frame.size.height - self.view.safeAreaInsets.bottom - 70 }, completion: {_ in animationView.play() }) // 自动消失逻辑改用DispatchWorkItem实现,你需要把dismissWorkItem声明为当前控制器的属性 self.dismissWorkItem = DispatchWorkItem { [weak self] in guard let self = self, let toastView = self.view.viewWithTag(1474) else { return } UIView.animate(withDuration: 0.2, delay: 0, options: .allowUserInteraction, animations: { toastView.center.y = self.view.frame.size.height + 50 }, completion: {_ in toastView.removeFromSuperview() }) } DispatchQueue.main.asyncAfter(deadline: .now() + duration, execute: self.dismissWorkItem!)
- 修改手势触发方法,手动取消自动消失任务
@objc func dismissToast(_ sender: UIGestureRecognizer) { guard let toastView = sender.view else { return } // 取消待执行的自动消失任务 self.dismissWorkItem?.cancel() // 移除所有已添加的动画 toastView.layer.removeAllAnimations() UIView.animate(withDuration: 0.2, delay: 0, options: .allowUserInteraction, animations: { toastView.center.y = self.view.frame.size.height + 50 }, completion: {_ in toastView.removeFromSuperview() }) }
- 可选:解决手势冲突
如果和页面其他手势存在冲突,可以遵守UIGestureRecognizerDelegate协议,添加以下代码:
swipeDownGesture.delegate = self // 实现代理方法 func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { return true }
内容的提问来源于stack exchange,提问作者goatofanerd
相关产品推荐
相关产品推荐

