どうしたんだい?
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を追加してください。
まとめ
- 原因に合わせた対処方法を確認
どうだったかな?
ありがとう!!!ケンティ!!!
私は今回は①の原因だった。