18

When I'm searching google and click on Etsy.com for exmaple, WKWebView redirect me to Etsy app installed on my iPhone. How can I disable this behavior? I want WKWebView to redirect me to etsy.com mobile website. I'm using swift.

gal
  • 929
  • 4
  • 21
  • 39
  • You could try intercepting the link in `WKNavigationDelegate` and show the website yourself. – saagarjha May 09 '16 at 18:01
  • Can you explain more please? – gal May 09 '16 at 18:54
  • 1
    Sure. If you implement `WKNavigationDelegate`, the method `webView(_ webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler decisionHandler: (WKNavigationActionPolicy) -> Void)` should be called whenever a link is clicked. Check the `navigationAction.request.URL` property to make sure it's not Etsy, for example; if it is, cancel the navigation using the decisionHandler and go to the website yourself using `loadRequest()`. Hopefully this will prevent Deep Linking. – saagarjha May 10 '16 at 04:25
  • There is no generic solution for this problem that will block all deep links? – gal May 10 '16 at 07:23
  • I haven't found one yet, unfortunately. – saagarjha May 11 '16 at 03:55
  • I'm better with switching to the Easy app for iPhone. It's a much better user experience. Perhaps you need to rethink your goals as a designer. – Vulkan May 15 '16 at 17:03
  • @user3737190 It is certainly not the best compliment you could do to gal, especially talking about an app that has nothing to do with etsy, what is Easy app? I know Easyjet. – Alessandro Ornano May 16 '16 at 16:40

4 Answers4

10

Unfortunately, WKWebView doesn’t send urls with custom schemes back to your app to handle automatically.

If you try this without special handling, it will look like your web view hangs after the user authenticates with the third-party service and you’ll never receive your callback. You could try using a redirect URI with the standard http or https scheme, but then WKWebView would just try to load it, rather than directing it out of the web view to your native app to handle.

In order to handle the redirect, you need to implement decidePolicyForNavigationAction in the WebPolicyDelegate of your WKWebView to detect the custom URL scheme and direct it to your app to be handled:

func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler: ((WKNavigationActionPolicy) -> Void)) {
        print("webView:\(webView) decidePolicyForNavigationAction:\(navigationAction) decisionHandler:\(decisionHandler)")

        let app = UIApplication.sharedApplication()
        let url = navigationAction.request.URL
        let myScheme: NSString = "https"
        if (url!.scheme == myScheme) && app.canOpenURL(url!) {
            print("redirect detected..")
            // intercepting redirect, do whatever you want
            app.openURL(url!) // open the original url
            decisionHandler(.Cancel)
            return
        }

        decisionHandler(.Allow)
    }

You can find detailed information here

Alessandro Ornano
  • 34,887
  • 11
  • 106
  • 133
0

Unfortunately, due to Universal Linking, you cannot rely on the url.scheme to detect when a link would be opened in another application any longer. However, the technique first described here by Alessandro Ornano does appear to still work. (I'm writing this in Xcode 14.3.1, for iOS 17.)

Here's a code snippet I'm using in my class that implements WKNavigationDelegate:

    func webView(
        _ webView: WKWebView,
        decidePolicyFor navigationAction: WKNavigationAction,
        decisionHandler: ((WKNavigationActionPolicy) -> Void)
    ) {
        if navigationAction.navigationType == .linkActivated,
           let url = navigationAction.request.url,
           case let urlString = url.absoluteString,
           urlShouldNotRedirect(urlString: urlString) {
            service.logger.info("found URL to not redirect: '\(urlString)', attempting to open in-app.")
            decisionHandler(.cancel)
            webView.load(navigationAction.request)
            return
        }
        decisionHandler(.allow)
    }

Note that, if we don't check the navigationAction.navigationType, this will result in an infinite redirect when the url isn't one that was just clicked. (As is the case with Google's search results as often as not, at least in my testing.)

Obviously, urlShouldNotRedirect() returns a boolean for whether or not I want to allow the redirect from a given url.absoluteString.

livingtech
  • 3,570
  • 29
  • 42
-1

i have installed the Etsy app and confirmed that searching "etsy" in Safari and tapping the first result (etsy.com) will launch the Etsy app.

i created a test "Single View Application" in Xcode and simply added the lines below to ViewController's viewDidLoad:

 override func viewDidLoad() {
     super.viewDidLoad()

     let webView = WKWebView(frame:view.bounds, configuration: WKWebViewConfiguration())
     view.addSubview(webView)
     webView.loadRequest(NSURLRequest(URL: NSURL(string: "https://www.google.com")!))
}

after searching for etsy and clicking on the first result it takes me to etsy.com in my test app (does not jump to the Etsy app).

have you done anything else in your code that could be causing WKWebView to allow redirects?

Casey
  • 6,531
  • 24
  • 43
  • This is because of Universal App Links using the Apple app site association file. Refer https://developer.apple.com/library/archive/documentation/General/Conceptual/AppSearch/UniversalLinks.html – Mrug Nov 01 '19 at 13:11
-3

Under normal circumstances the WKWebView should not be opening a 3rd party app instead of going to the web site - but I know of 2 exceptions

  • If you have explicitly inserted some code in a WKNavigationDelegate handler to open the 3rd party app
  • If iOS isn't working quite right (restart the device to fix) - there seems to be a bug, which occasionally creates the behavior you are describing (Observed in iOS10.2)
Hugo
  • 974
  • 9
  • 21