その他

「Webviewでリンクが開かない?解決方法をご紹介!」

のんちゃん
のんちゃん
あれ〜リンクがあるのに遷移できないよぉ
ケンティ
ケンティ

どうしたんだい?

のんちゃん
のんちゃん

iOSのアプリ開発をしているんだけど、WebViewのリンクに遷移しないんだよ。。

ケンティ
ケンティ

これはiPhoneの開発時によくあることだね!!

のんちゃん
のんちゃん

どうしたらいいの?

ケンティ
ケンティ

それでは今回はWebviewでリンクが開かない?】に関してお話ししましょう。

WebViewとは

Webviewとはアプリの中でWebページを表示する機能です。

アプリ内でWebページを表示させることができるので

アプリと連携したコンテンツやサービスなどを提供することができます。

しかしWebviewでリンクを遷移させると、リンクが開かないという問題が発生することが多々あります。

原因から解決方法を特定しよう

まずは原因を特定しよう。

iOSアプリ開発におけるWebviewでリンクが開かない問題は

下記が原因であることが多いです。

①リンクのターゲット設定が正しくない

②リンク先が存在しない

③HTTP/HTTPSの違い

④Javascriptの制限

⑤ネットワーク接続の問題

①リンクのターゲット設定が正しくない

Webviewではtarget=”_blank”target=”_parent”のような

新規ウィンドウまたは親ウィンドウでリンクを開く属性がサポートされていません。

すべてのリンクはデフォルトで現在のWebviewで開かれるものとして扱われます。

リンクの遷移を行う前に、HTML内に設定されている<a>タグにて

リンク先の遷移先のターゲット属性を明示的に指定すると遷移が可能になります。

<a href="https://example.com" target="_self">Link</a>

②リンク先が存在しない

コンテンツのリンク先が無効な場合

例えば404エラーなどのリンク遷移は失敗します。

この場合はコンテンツをホストするWebサーバーで

エラーページの表示などが行われるので

リンク先を再確認する必要があります。

③HTTP/HTTPSの違い

WebviewはデフォルトではHTTPリクエストを送信するため

リクエスト先の遷移時にHTTPSのセキュリティ上の制限がある場合があります。

この場合はアプリ内の設定や改修でHTTPリクエストを送信できるように修正する必要があります。

HTTPリクエストを送信できるようにする

HTTPリクエストを送信できるようにATS(App Transport Security)を無効にするATSは、iOS 9以降で導入されたセキュリティ機能です。

TLS/SSLに基づくセキュアな通信を強制することで

ユーザーのデータを保護します。

しかし最新の動向に追随していないWebサイトにアクセスする際に問題が発生することがあり

この場合はATSを無効にする必要があります。

ATSを無効にするには、Info.plistファイルに以下の設定を追加します。

<key>NSAppTransportSecurity</key>
 <dict>
     <key>NSAllowsArbitraryLoads</key>
     <true/>
 </dict>

HTTPリクエストを送信するためにWebViewを修正する

Webviewのリソースローダーを独自で設定することで

HTTPを使用するリクエストを処理できます。

以下は、SwiftでWebviewをHTTPリクエストを送信できるように構成する方法の例です。

if let url = URL(string: "http://example.com") {
    let urlRequest = URLRequest(url: url)
    webView.loadRequest(urlRequest)
}

ただし、セキュリティ上の理由からHTTPリクエストを使用することはお勧めできません。

できるだけHTTPSでリクエストを送信するようにし

ATSを有効にしてユーザーのデータを保護することをオススメします。

④Javascriptの制限

WebviewではJavaScriptの実行が無効になっている可能性があります。

JavaScriptは多くのウェブサイトで必須の機能であり

JavaScriptを有効にすることで、リンクの遷移が可能になる場合があります。

JavaScriptが無効になっている場合には、WebviewのオプションでJavaScriptの有効化を行う必要があります。

import UIKit
import WebKit

class ViewController: UIViewController, WKNavigationDelegate {

    var webView: WKWebView!

    override func loadView() {
        webView = WKWebView()
        webView.navigationDelegate = self
        view = webView
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        let url = URL(string: "https://www.example.com")!
        webView.load(URLRequest(url: url))

        webView.configuration.preferences.javaScriptEnabled = true // JavaScriptを有効にする
    }

}

上記例では、WKWebViewを使用しています。

この例をベースに、必要に応じて実際のURLを追加して

JavaScriptが有効になっていることを確認してください。

⑤ネットワーク接続の問題

Webview内でのコンテンツ表示やリンクの遷移は

ネットワーク接続によって制限される場合があります。

ネットワーク接続が正常でない場合には

アプリ内の設定や改修で接続を確認し

接続できるように改善する必要があります。

import UIKit
import WebKit
import SystemConfiguration

class ViewController: UIViewController, WKNavigationDelegate {

    var webView: WKWebView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Reachabilityを使用してネットワーク接続状態を判断する
        let reachability = SCNetworkReachabilityCreateWithName(nil, "www.google.com")
        var flags = SCNetworkReachabilityFlags()
        SCNetworkReachabilityGetFlags(reachability!, &flags)

        if flags.contains(.reachable) { // ネットワークに接続されている場合
            webView = WKWebView(frame: self.view.frame)
            self.view.addSubview(webView)

            webView.navigationDelegate = self
            
            let url = URL(string: "https://www.example.com")!
            webView.load(URLRequest(url: url))
        } else { // ネットワークに接続されていない場合
            let alert = UIAlertController(title: "ネットワーク接続エラー", message: "ネットワークに接続されていません。接続を確認してください。", preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
            present(alert, animated: true, completion: nil)
        }
    }
    
    // WKNavigationDelegateを使用して、リクエスト完了時に呼び出されるdidFinishメソッドも実装することができます。
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        print("リクエスト完了")
    }

}

上記の例ではSCNetworkReachabilityCreateWithNameを使用して

ネットワークに接続できるかどうかを判断しています。

webViewを使用してWKWebViewインスタンスを生成して表示しているのは

ネットワークに接続できる場合のみです。

ネットワーク接続がされていない場合は

UIAlertControllerでメッセージを表示しています。

必要であれば、didFinishメソッドを使用して

リクエスト完了時に必要な処理を実装することもできます。

必要な場合には、上記の例を参考にして実際のURLを追加してください。

まとめ

まとめ
  • 原因に合わせた対処方法を確認
ケンティ
ケンティ

どうだったかな?

のんちゃん
のんちゃん

ありがとう!!!ケンティ!!!

私は今回は①の原因だった。