wkwebview decidePolicyForNavigationAction being ca

2019-02-11 00:53发布

问题:

I tried to override the original wkwebview actionsheet...

Firstly I disabled the original wkactionsheet by webView.evaluateJavaScript("document.body.style.webkitTouchCallout='none';", completionHandler: nil)

Then I initialise a long press gesture recogniser (and it works perfectly) and I created my own action sheet. I used decidePolicyForNavigationAction to get the clicked link urls:

func onLongPress(gestureRecognizer:UIGestureRecognizer){
        if gestureRecognizer.state == UIGestureRecognizerState.Began {
            longPressSwitch = true
        }
    }

func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) {
        if(navigationAction.navigationType == .LinkActivated) {
            longPressAcUrl = navigationAction.request.URL!.absoluteString
            if(longPressSwitch == true) {
                let ac = actionMenu(self)
                self.presentViewController(ac, animated: true) {

                }
                decisionHandler(.Cancel)
                longPressSwitch = false
            }
        }
        decisionHandler(.Allow)
    }

The problem is, the action sheet shows up after the finger is releasing (i.e., recogniser.state = .Ended) but I want it shows up like Chrome, which should be 0.5 or less seconds after the user pressing the link... (i.e., recogniser.state = .Begin), what can I do?

ps: this is my action sheet:

//Rebuild Wkactionsheet
    func actionMenu(sender: UIViewController) -> UIAlertController {
        let alertController = UIAlertController(title: "", message: longPressAcUrl, preferredStyle: .ActionSheet)
        let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel) { (action) in

        }
        alertController.addAction(cancelAction)
        let openAction = UIAlertAction(title: "Open", style: .Default) { (action) in
            //...
        }
        alertController.addAction(openAction)
        let opentabAction = UIAlertAction(title: "Open in New Tab", style: .Default) { (action) in
            //...
        }
        alertController.addAction(opentabAction)
        let copyurlAction = UIAlertAction(title: "Copy Link URL", style: .Default) { (action) in
            //...
        }
        alertController.addAction(copyurlAction)

        return alertController
    }

also, if I tried to put

let ac = actionMenu(self)
self.presentViewController(ac, animated: true) {}

at onLongPress(), it works fine although this can't get URL (longPressAcUrl) from navigationAction.request.URL!.absoluteString!

回答1:

First of all, there's no need to mimic Chrome's behavior because there's little to no consequences to the whole experience. In fact, one could theorize your approach of having it show up after the finger is released is better than what Chrome and Safari is doing.

Why?

Because you are using the standard behavior of the standard long press recognition that is omnipresent throughout the entire ecosystem.

I believe Safari is showing up the action sheet while the user is pressing to give the illusion that everything is happening FAST.

Anyway, you can "fix" this by creating a custom UIWindow, implementing your own long press recognition and getting the elements of the HTML using saved coordinates. For a guide on how to create this entire behavior check this link: http://www.icab.de/blog/2010/07/11/customize-the-contextual-menu-of-uiwebview/comment-page-3/

(Objective-C)

Use UIGestureRecognizerStateBegan

A general bug: Websites will bypass the policy decision and will load the content when a touch ends.