【问题标题】:Can't handle touches simultaneously with WKWebView on iOS 13.4无法在 iOS 13.4 上与 WKWebView 同时处理触摸
【发布时间】:2020-04-14 13:28:10
【问题描述】:

问题: 从 iOS 13.4 开始,WebKit 会拦截之前传递给系统的手势,并且可以同时被UIGestureRecognizer 处理

演示项目: 我创建了WKWebView 并将其添加到UIViewController 的视图中。我还创建了UIPinchGestureRecognizer 并将其添加到UIViewControler 的视图中。

class ViewController: UIViewController, UIGestureRecognizerDelegate, WKNavigationDelegate {

    var webView: WKWebView?

    override func viewDidLoad() {
        super.viewDidLoad()

        let pinch = UIPinchGestureRecognizer(target: self, action: #selector(self.pinchHandler))
        pinch.delegate = self
        self.view.addGestureRecognizer(pinch)

        addWebView()
    }

    func addWebView() {
        let webView = WKWebView()
        webView.translatesAutoresizingMaskIntoConstraints = false
        self.view.addSubview(webView)
        NSLayoutConstraint.activate([
            webView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            webView.topAnchor.constraint(equalTo: view.topAnchor),
            webView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            webView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        ])

        self.webView = webView
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        if let localHtmlFile = Bundle.main.url(forResource: "index", withExtension: "html") {
            let request = URLRequest(url: localHtmlFile)
            webView?.load(request)
        }
    }

    @objc func pinchHandler() {
        debugPrint("PinchHandler called")
    }

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive event: UIEvent) -> Bool {
        if event.type == .touches {
            return true
        }
        return false
    }

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
        return true
    }
}

我尝试运行添加到主包的示例 html 网站:

<html>
    <head>
        <style>
            .center {
              width: 100%;
              height: 100%;
              border: 3px solid #73AD21;
              text-align: center;
              font-size: 100;
              overflow: hidden;
            }
        </style>
        <script>
            function move(event) {
                console.log(event);
                event.preventDefault()
            }
        </script>
    </head>

    <body ontouchmove="move(event)" class="center">
            <p id="content">
                demo
            </p>
    </body
</html>

网站拦截touchmove 事件,我在move(event) 函数中取消它。

当我在 iOS 13.0 模拟器上运行此代码 10 次时,每次我的处理程序工作。当我在 iOS 13.4 模拟器上运行此代码 10 次时,我的捏处理程序工作了 4 次,但没有工作 6 次。

【问题讨论】:

  • 嗨!我也在经历同样的事情,你找到解决方法了吗?
  • 不幸的是仍然没有解决方法:/

标签: swift webkit uigesturerecognizer ios13.4


【解决方案1】:

我最终切换到使用 Javascript 来检测 web 视图上的点击。 一个正在运行的游乐场,展示了如何做到这一点:

import UIKit
import PlaygroundSupport
import WebKit

class TouchDetectionOnWKWebViewUsingJSDemoVC : UIViewController, WKScriptMessageHandler {
  override func loadView() {
    let config = WKWebViewConfiguration()
    let webView = WKWebView(frame: .init(origin: .zero, size: .init(width: 100, height: 200)), configuration: config)

    let jsEvent = "touchstart"
    let handlerName = "handler"
    let jsCode =
    """
    window.addEventListener('\(jsEvent)', function(e) {
      window.webkit.messageHandlers.\(handlerName).postMessage('\(jsEvent)')
    })
    """

    let jsScript = WKUserScript(source: jsCode, injectionTime: .atDocumentEnd, forMainFrameOnly: false)
    config.userContentController.addUserScript(jsScript)
    config.userContentController.add(self, name: handlerName)

    let demoURL = URL(string: "https://developer.apple.com/")!
    webView.load(URLRequest(url: demoURL))

    self.view = webView
  }

  func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
    print(message.body)
  }
}

PlaygroundPage.current.liveView = TouchDetectionOnWKWebViewUsingJSDemoVC()

在示例中,我展示了如何监听 touchstart 事件,但它可以是任何 js 事件,例如:touchendtouchmovegesturestartgestureend 等。我们甚至可以监听滚动事件(但我认为最好成为 webView.scrollView 代表)。

【讨论】:

  • 问题是有一个内部监听器,我无法访问,它通过调用event.preventDefault() 停止响应链,所以我的监听器没有收到消息。
猜你喜欢
  • 2020-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
相关资源
最近更新 更多