首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何监视WKWebview上的请求?

如何监视WKWebview上的请求?
EN

Stack Overflow用户
提问于 2015-02-27 13:51:44
回答 4查看 25.8K关注 0票数 19

如何监视WKWebview上的请求?

我尝试使用NSURLprotocol (canInitWithRequest),但它不会监视ajax请求,只监视导航请求(文档请求)

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2015-03-03 09:40:44

最后我解决了

由于我无法控制web视图内容,所以我向WKWebview注入了一个包含jQuery AJAX请求侦听器的java脚本。

当侦听器捕获请求时,它将方法中的请求主体发送给本机应用程序:

代码语言:javascript
复制
webkit.messageHandlers.callbackHandler.postMessage(data);

本机应用程序在一个名为:

代码语言:javascript
复制
(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message

并执行相应的操作。

以下是相关代码:

ajaxHandler.js -

代码语言:javascript
复制
//Every time an Ajax call is being invoked the listener will recognize it and  will call the native app with the request details

$( document ).ajaxSend(function( event, request, settings )  {
    callNativeApp (settings.data);
});

function callNativeApp (data) {
    try {
        webkit.messageHandlers.callbackHandler.postMessage(data);
    }
    catch(err) {
        console.log('The native context does not exist yet');
    }
}

我的ViewController代表是:

代码语言:javascript
复制
@interface BrowserViewController : UIViewController <UIWebViewDelegate, WKUIDelegate, WKNavigationDelegate, WKScriptMessageHandler, UIWebViewDelegate>

在我的viewDidLoad()中,我正在创建一个WKWebView:

代码语言:javascript
复制
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc]init];
[self addUserScriptToUserContentController:configuration.userContentController];
appWebView = [[WKWebView alloc]initWithFrame:self.view.frame configuration:configuration];
appWebView.UIDelegate = self;
appWebView.navigationDelegate = self;
[appWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString: @"http://#############"]]];                                                     

下面是addUserScriptToUserContentController:

代码语言:javascript
复制
- (void) addUserScriptToUserContentController:(WKUserContentController *) userContentController{
    NSString *jsHandler = [NSString stringWithContentsOfURL:[[NSBundle mainBundle]URLForResource:@"ajaxHandler" withExtension:@"js"] encoding:NSUTF8StringEncoding error:NULL];
    WKUserScript *ajaxHandler = [[WKUserScript alloc]initWithSource:jsHandler injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:NO];
    [userContentController addScriptMessageHandler:self name:@"callbackHandler"];
    [userContentController addUserScript:ajaxHandler];
}
票数 35
EN

Stack Overflow用户

发布于 2018-09-21 07:03:44

@Benzi的答案很好,但是它使用的是jQuery,它似乎不再在WKWebView中工作了,所以我找到了不使用jQuery的解决方案。

下面是ViewController实现,它可以通知您每个AJAX请求都是在WKWebView中完成的。

代码语言:javascript
复制
import UIKit
import WebKit

class WebViewController: UIViewController {

    private var wkWebView: WKWebView!
    private let handler = "handler"

    override func viewDidLoad() {
        super.viewDidLoad()

        let config = WKWebViewConfiguration()
        let userScript = WKUserScript(source: getScript(), injectionTime: .atDocumentStart, forMainFrameOnly: false)
        config.userContentController.addUserScript(userScript)
        config.userContentController.add(self, name: handler)

        wkWebView = WKWebView(frame:  view.bounds, configuration: config)
        view.addSubview(wkWebView)

        if let url = URL(string: "YOUR AJAX WEBSITE") {
            wkWebView.load(URLRequest(url: url))
        } else {
            print("Wrong URL!")
        }
    }

    private func getScript() -> String {
        if let filepath = Bundle.main.path(forResource: "script", ofType: "js") {
            do {
                return try String(contentsOfFile: filepath)
            } catch {
                print(error)
            }
        } else {
            print("script.js not found!")
        }
        return ""
    }
}

extension WebViewController: WKScriptMessageHandler {
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        if let dict = message.body as? Dictionary<String, AnyObject>, let status = dict["status"] as? Int, let responseUrl = dict["responseURL"] as? String {
            print(status)
            print(responseUrl)
        }
    }
}

相当标准的实现。有一个以编程方式创建的WKWebView。有从script.js文件加载的注入脚本。

最重要的部分是script.js文件:

代码语言:javascript
复制
var open = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function() {
    this.addEventListener("load", function() {
        var message = {"status" : this.status, "responseURL" : this.responseURL}
        webkit.messageHandlers.handler.postMessage(message);
    });
    open.apply(this, arguments);
};

每次加载userContentController请求时都会调用AJAX委托方法。我正在传递statusresponseURL,因为在我的情况下,这是我所需要的,但是您也可以获得更多关于请求的信息。以下是所有可用属性和方法的列表:https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest

我的解决方案灵感来自@John:https://stackoverflow.com/a/27363569/3448282所写的答案

票数 18
EN

Stack Overflow用户

发布于 2015-03-02 06:25:38

如果您控制了WkWebView中的内容,只要您发出ajax请求,就可以使用window.webkit.messageHandlers向您的本地应用程序发送消息,该请求将作为WKScriptMessage接收,无论您指定的是什么WKScriptMessageHandler,都可以对其进行处理。消息可以包含您想要的任何信息,并将自动转换为目标-C或Swift代码中的本机对象/值。

如果您没有对内容的控制,仍然可以通过通过一个JavaScript注入您自己的WKUserScript来跟踪ajax请求并使用上面提到的方法发送回消息。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28766676

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档