_func webView(webView: WKWebView!, decidePolicyForNavigationAction navigationAction: WKNavigationAction!, decisionHandler: ((WKNavigationActionPolicy) -> Void)!) {
var request = NSMutableURLRequest(URL: navigationAction.request.URL)
request.setValue("value", forHTTPHeaderField: "key")
decisionHandler(.Allow)
}
_
上記のコードで、リクエストにヘッダーを追加します。 navigationAction.request.setValue("IOS", forKey: "DEVICE_APP")
を実行しようとしましたが、機能しません。
どうぞ私を助けてください。
残念なことに、残念ながらWKWebView
を使用してこれを行うことはできません。
webView:decidePolicyForNavigationAction:decisionHandler:
なぜなら navigationAction.request
は読み取り専用であり、変更できない変更不可能なNSURLRequest
インスタンスです。
私が正しく理解している場合、WKWebView
は別のコンテンツおよびネットワークプロセスでサンドボックス化されて実行されます。少なくともiOSでは、ネットワークリクエストを傍受または変更する方法はありません。
UIWebView
に戻ると、これを行うことができます。
これにはさまざまな方法がありますが、最も簡単な解決策は、WKWebViewをサブクラス化してloadRequestメソッドをオーバーライドすることです。このようなもの:
class CustomWebView: WKWebView {
override func loadRequest(request: NSURLRequest) -> WKNavigation? {
guard let mutableRequest = request.mutableCopy() as? NSMutableURLRequest else {
return super.loadRequest(request)
}
mutableRequest.setValue("custom value", forHTTPHeaderField: "custom field")
return super.loadRequest(mutableRequest)
}
}
次に、CustomWebViewクラスをWKWebViewであるかのように使用します。
EDIT NOTE:これは、@ Stefan Arentzによって指摘された最初のリクエストでのみ機能します。
[〜#〜]注[〜#〜]:一部のフィールドは上書きできず、変更されません。完全なテストは行っていませんが、User-Agent
フィールドは、特定のハックを行わない限りオーバーライドできません( その回答についてはここをチェックしてください )
Jonnyが示唆したように、Au Risの回答をNavigationAction
ではなくNavigationResponse
を使用するように変更しました。また、これにより、同じURLが後で呼び出され、現在のURLを追跡する必要がなくなる状況が修正されます。これはGETリクエストに対してのみ機能しますが、必要に応じて他のリクエストタイプに確実に適合させることができます。
import UIKit
import WebKit
class ViewController: UIViewController, WKNavigationDelegate {
var webView: WKWebView?
override func viewDidLoad() {
super.viewDidLoad()
webView = WKWebView(frame: CGRect.zero)
webView!.navigationDelegate = self
view.addSubview(webView!)
// [...] set constraints and stuff
// Load first request with initial url
loadWebPage(url: "https://my.url")
}
func loadWebPage(url: URL) {
var customRequest = URLRequest(url: url)
customRequest.setValue("true", forHTTPHeaderField: "x-custom-header")
webView!.load(customRequest)
}
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping
(WKNavigationActionPolicy) -> Void) {
if navigationAction.request.httpMethod != "GET" || navigationAction.request.value(forHTTPHeaderField: "x-custom-header") != nil {
// not a GET or already a custom request - continue
decisionHandler(.allow)
return
}
decisionHandler(.cancel)
loadWebPage(url: navigationAction.request.url!)
}
}
いくつかの制限がありますが、それは可能です。デリゲート関数_webView:decidePolicyFornavigationResponse:decisionHandler:
_で応答をインターセプトします。URLが変更された場合は、decisionHandler(.cancel)
を渡してキャンセルし、カスタムヘッダーとインターセプトされたURLを設定するnew URLRequest
でWebビューをリロードします。このようにして、URLが変更されるたびに(ユーザーがリンクをタップするなど)、その要求をキャンセルし、カスタムヘッダーを使用して新しい要求を作成します。
_import UIKit
import WebKit
class ViewController: UIViewController, WKNavigationDelegate {
var webView: WKWebView?
var loadUrl = URL(string: "https://www.google.com/")!
override func viewDidLoad() {
super.viewDidLoad()
webView = WKWebView(frame: CGRect.zero)
webView!.navigationDelegate = self
view.addSubview(webView!)
webView!.translatesAutoresizingMaskIntoConstraints = false
webView!.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true
webView!.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true
webView!.topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive = true
webView!.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0).isActive = true
// Load first request with initial url
loadWebPage(url: loadUrl)
}
func loadWebPage(url: URL) {
var customRequest = URLRequest(url: url)
customRequest.setValue("some value", forHTTPHeaderField: "custom header key")
webView!.load(customRequest)
}
// MARK: - WKNavigationDelegate
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
guard let url = (navigationResponse.response as! HTTPURLResponse).url else {
decisionHandler(.cancel)
return
}
// If url changes, cancel current request which has no custom headers appended and load a new request with that url with custom headers
if url != loadUrl {
loadUrl = url
decisionHandler(.cancel)
loadWebPage(url: url)
} else {
decisionHandler(.allow)
}
}
}
_
private var urlrequestCurrent: URLRequest?
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
//print("WEB decidePolicyFor navigationAction: \(navigationAction)")
if let currentrequest = self.urlrequestCurrent {
//print("currentrequest: \(currentrequest), navigationAction.request: \(navigationAction.request)")
if currentrequest == navigationAction.request {
self.urlrequestCurrent = nil
decisionHandler(.allow)
return
}
}
decisionHandler(.cancel)
var customRequest = navigationAction.request
customRequest.setValue("myvaluefffs", forHTTPHeaderField: "mykey")
self.urlrequestCurrent = customRequest
webView.load(customRequest)
}