func webView(webView: WKWebView!, decidePolicyForNavigationAction navigationAction: WKNavigationAction!, decisionHandler: ((WKNavigationActionPolicy) -> Void)!) {
var request = NSMutableURLRequest(URL: navigationAction.request.URL)
request.setValue("value", forHTTPHeaderField: "key")
decisionHandler(.Allow)
}
Dans le code ci-dessus, je souhaite ajouter un en-tête à la demande. J'ai essayé de faire navigationAction.request.setValue("IOS", forKey: "DEVICE_APP")
mais ça ne marche pas.
aidez-moi de quelque manière que ce soit.
Malheureusement, vous ne pouvez pas faire cela avec WKWebView
.
Cela ne fonctionne très certainement pas dans webView:decidePolicyForNavigationAction:decisionHandler:
car le navigationAction.request
est en lecture seule et une instance NSURLRequest
non mutable que vous ne pouvez pas modifier.
Si je comprends bien, WKWebView
s'exécute en sandbox dans un processus de contenu et de réseau distinct et, du moins sur iOS, il n'existe aucun moyen d'intercepter ou de modifier ses demandes réseau.
Vous pouvez le faire si vous revenez à UIWebView
.
Il existe de nombreuses façons de le faire. J'ai trouvé que la solution la plus simple consistait à sous-classer WKWebView et à remplacer la méthode loadRequest. Quelque chose comme ça:
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)
}
}
Ensuite, utilisez simplement la classe CustomWebView comme s'il s'agissait d'un WKWebView.
EDIT NOTE : Ceci ne fonctionnera que sur la première requête, comme l'a souligné @Stefan Arentz.
NOTE: Certains champs ne peuvent pas être remplacés et ne seront pas modifiés. Je n'ai pas fait de test approfondi mais je sais que le champ User-Agent
ne peut pas être remplacé à moins que vous ne fassiez un piratage spécifique ( vérifiez ici la réponse à cette question )
Avec certaines limitations, mais vous pouvez le faire. Intercepter la réponse dans la fonction déléguée webView:decidePolicyFornavigationResponse:decisionHandler:
. Si les modifications apportées à l'URL, annulez-la en passant decisionHandler(.cancel)
et rechargez la vue Web avec newURLRequest
, qui définit les en-têtes personnalisés et l'URL interceptée. De cette manière, chaque fois qu'une URL change (par exemple, les utilisateurs tapent sur des liens), vous annulez cette demande et créez une nouvelle avec des en-têtes personnalisés.
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)
}
}
}
J'ai modifié la réponse Au Ris pour utiliser NavigationAction
au lieu de NavigationResponse
, comme suggéré par jonny. En outre, cela corrige les situations où la même URL est appelée ultérieurement et vous n'avez plus à suivre l'URL actuelle. Cela ne fonctionne que pour les requêtes GET mais peut sûrement être adapté pour d'autres types de requête si nécessaire.
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!)
}
}
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)
}