web-dev-qa-db-ja.com

WKWebViewで電話/メール/マップリンクを起動する

KINWebBrowser は、iOSアプリ用のオープンソースのWebブラウザーモジュールです。最近、KINWebBrowserをアップグレードして WKWebView を使用してUIWebViewの段階的廃止を開始しました。これは大幅な改善をもたらしますが、

問題:WKWebViewでは、ユーザーは電話番号、電子メールアドレス、マップなどのURLを含むリンクを起動できません。

表示されたページからリンクとして起動されたときに、これらの代替URLの標準iOS動作を起動するようにWKWebViewを構成するにはどうすればよいですか?

コードのすべてがここにあります

WKWebKit に関する詳細情報

こちらのKINWebBrowser GitHubの 問題をご覧ください

20
dfmuir

この関数をKINWebBrowserViewController.mに追加することで、Googleマップリンク(target = "_ blank"に関連しているように見える)およびtel:スキームで機能するようにできました

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
    if(webView != self.wkWebView) {
        decisionHandler(WKNavigationActionPolicyAllow);
        return;
    }

    UIApplication *app = [UIApplication sharedApplication];
    NSURL         *url = navigationAction.request.URL;

    if (!navigationAction.targetFrame) {
        if ([app canOpenURL:url]) {
            [app openURL:url];
            decisionHandler(WKNavigationActionPolicyCancel);
            return;
        }
    }
    if ([url.scheme isEqualToString:@"tel"])
    {
        if ([app canOpenURL:url])
        {
            [app openURL:url];
            decisionHandler(WKNavigationActionPolicyCancel);
            return;
        }
    }
    decisionHandler(WKNavigationActionPolicyAllow);
}
24
Darren Ehlers

Xcode 8.1、Swift 2.3で動作します。

Target = "_ blank"の場合、電話番号(tel :)およびメール(mailto :)リンク。

func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) {
    if webView != self.webview {
        decisionHandler(.Allow)
        return
    }

    let app = UIApplication.sharedApplication()
    if let url = navigationAction.request.URL {
        // Handle target="_blank"
        if navigationAction.targetFrame == nil {
            if app.canOpenURL(url) {
                app.openURL(url)
                decisionHandler(.Cancel)
                return
            }
        }

        // Handle phone and email links
        if url.scheme == "tel" || url.scheme == "mailto" {
            if app.canOpenURL(url) {
                app.openURL(url)
                decisionHandler(.Cancel)
                return
            }
        }

        decisionHandler(.Allow)
    }
}

Swift 4.の更新

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {

    if webView != self.webView {
        decisionHandler(.allow)
        return
    }

    let app = UIApplication.shared
    if let url = navigationAction.request.url {
        // Handle target="_blank"
        if navigationAction.targetFrame == nil {
            if app.canOpenURL(url) {
                app.open(url)
                decisionHandler(.cancel)
                return
            }
        }

        // Handle phone and email links
        if url.scheme == "tel" || url.scheme == "mailto" {
            if app.canOpenURL(url) {
                app.open(url)
            }

            decisionHandler(.cancel)
            return
        }

        decisionHandler(.allow)
    }

}
10
Victor Almeida

これを正しく行うには、他のコールバックを実装する必要があります(Swift 5.0)。

// Gets called if webView cant handle URL
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
  guard let failingUrlStr = (error as NSError).userInfo["NSErrorFailingURLStringKey"] as? String  else { return }
  let failingUrl = URL(string: failingUrlStr)!

  switch failingUrl {
    // Needed to open Facebook
    case _ where failingUrlStr.startsWith("fb:"):
    if #available(iOS 10.0, *) {
       UIApplication.shared.open(failingUrl, options: [:], completionHandler: nil)
       return
    } // Else: Do nothing, iOS 9 and earlier will handle this

  // Needed to open Mail-app
  case _ where failingUrlStr.startsWith("mailto:"):
    if UIApplication.shared.canOpenURL(failingUrl) {
      UIApplication.shared.open(failingUrl, options: [:], completionHandler: nil)
      return
    }

  // Needed to open Appstore-App
  case _ where failingUrlStr.startsWith("itmss://iTunes.Apple.com/"):
    if UIApplication.shared.canOpenURL(failingUrl) {
      UIApplication.shared.open(failingUrl, options: [:], completionHandler: nil)
      return
    }

  default: break
  }
}

Facebook、Mail、Appstoreなど、Safariを開かなくてもアプリから直接呼び出せるようになりました

7
2h4u

WkwebviewでGmailの添付ファイルを開く方法を探して、ここに着陸しました。

私の解決策は簡単です:

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
    if navigationAction.targetFrame == nil, let redirect = navigationAction.request.url {
        if UIApplication.shared.canOpenURL(redirect) {
            self.webViewMail?.load(navigationAction.request)
            decisionHandler(.cancel)
            return
        }
    }
    decisionHandler(.allow)
}
1
Luca Davanzo

これはXcode 8 WKWebviewに役立ちます

func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
    if navigationAction.targetFrame == nil {
        let url = navigationAction.request.url
        if url?.description.range(of: "http://") != nil || url?.description.range(of: "https://") != nil || url?.description.range(of: "mailto:") != nil || url?.description.range(of: "tel:") != nil  {
            UIApplication.shared.openURL(url!)
        }
    }
    return nil
}

編集済み:

リンクには属性target="_blank"を指定する必要があります。

1
Abduhafiz

Swift 4.2の更新

古い投稿を掘り下げて申し訳ありませんが、私は同じ問題を抱えていて、Swift 4.2。うまくいけば、次回WKWebViewで作業するときにそれを見つけてください!

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {

    let url = navigationAction.request.url?.absoluteString
    let urlElements = url?.components(separatedBy: ":") ?? []

    switch urlElements[0] {

    case "tel":
        UIApplication.shared.openURL(navigationAction.request.url!)
        decisionHandler(.cancel)
    case "mailto":
        UIApplication.shared.openURL(navigationAction.request.url!)
        decisionHandler(.cancel)
    default:
        decisionHandler(.allow)
    }
}

私はインスピレーションとして次のサイトを使用しました:

SubzDesignz iOS Swift 4 WKWebview – Detect tel、mailto、target =” _ blank” and CheckConnection

1
Iain Coleman

上記の答えは私にとってはうまくいきますが、Swift 2.3

if navigationAction.targetFrame == nil {
    let url = navigationAction.request.mainDocumentURL
    if url?.description.rangeOfString("mailto:")?.startIndex != nil ||
        url?.description.rangeOfString("tel:")?.startIndex != nil
    {
        if #available(iOS 10, *) {
            UIApplication.sharedApplication().openURL(url!,options: [:], completionHandler: nil)
        } else {
            UIApplication.sharedApplication().openURL(url!)  // deprecated
        }
    }
}
0
Philipp Homann