理论:
UIPageViewController 和 UITableView 都使用UIScrollView 实现,其中UIPageViewController 嵌入UIScrollView 和UITableView 是UIScrollView 的子类
UITableView 还使用了几个UIPanGestureRecognizers 来引入所有的魔法。其中之一是UISwipeActionPanGestureRecognizer,它处理滑动删除操作。
这个问题是因为UIPageViewControllers UIPanGestureRecognizer在与UITableViews UISwipeActionPanGestureRecognizers的冲突中获胜。
因此,如果UITableViews UISwipeActionPanGestureRecognizer 在起作用,我们必须知道如何告诉UIPageViewController 忽略手势。
幸运的是UIGestureRecognizer已经提供了一些东西。
UIGestureRecognizer 的require(toFail otherGestureRecognizer: UIGestureRecognizer) 在两个手势识别器之间创建一个关系,这将阻止手势的动作被调用,直到另一个手势识别器失败。
所以我们所要做的就是在UITableViews UISwipeActionPanGestureRecognizer 被触发时使UIPageViewControllers 嵌入UIScrollviews panGestureRecognizer 失败。
有两种方法可以实现。
解决方案 1:向表格视图和 Mimic UISwipeActionPanGestureRecognizer 添加新的手势识别器。并使 UIPageViewController panGesture 要求使这个新的gestureRecognizer 失败
解决方案 2(有点脏):与UITableView 的UISwipeActionPanGestureRecognizer 进行字符串比较,并使UIPageViewController panGesture 要求使这个新的手势识别器失败
代码:
解决方案 1
一个有用的实用程序,可让 UIPageViewControllers 嵌入 UIScrollView
extension UIPageViewController {
var scrollView: UIScrollView? {
return view.subviews.first { $0 is UIScrollView } as? UIScrollView
}
}
将下面的代码添加到UIViewController 持有UITableView 并从viewDidLoad() 调用它
func handleSwipeDelete() {
if let pageController = parent?.parent as? UIPageViewController {
let gestureRecognizer = UIPanGestureRecognizer(target: self, action: nil)
gestureRecognizer.delaysTouchesBegan = true
gestureRecognizer.cancelsTouchesInView = false
gestureRecognizer.delegate = self
tableView.addGestureRecognizer(gestureRecognizer)
pageController.scrollView?.canCancelContentTouches = false
pageController.scrollView?.panGestureRecognizer.require(toFail: gestureRecognizer)
}
}
最后是委托方法
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
guard let panGesture = gestureRecognizer as? UIPanGestureRecognizer else {
return false
}
let translation = panGesture.translation(in: tableView)
// In my case I have only trailing actions, so I used below condition.
return translation.x < 0
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer,
shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return otherGestureRecognizer.view == tableView
}
解决方案 2(有点脏)
一个有用的实用程序,可让 UIPageViewControllers 嵌入 UIScrollView
extension UIPageViewController {
var scrollView: UIScrollView? {
return view.subviews.first { $0 is UIScrollView } as? UIScrollView
}
}
将下面的代码添加到UIViewController 持有UITableView 并从viewDidLoad() 调用它
func handleSwipeDelete() {
guard let pageController = parent as? UIPageViewController else {
return
}
pageController.scrollView?.canCancelContentTouches = false
tableView.gestureRecognizers?.forEach { recognizer in
let name = String(describing: type(of: recognizer))
guard name == "_UISwipeActionPanGestureRecognizer" else {
return
}
pageController.scrollView?
.panGestureRecognizer
.require(toFail: recognizer)
}
}