UIWebView 完成加载时获取回调 Ajax
Get callback when UIWebView finishes loading Ajax
是否可以在 Ajax 完成 UIWebView 加载时收到通知?在 Android 我可以这样做:
@SuppressLint("SetJavaScriptEnabled")
private void setUpWebView() {
webview = view.findViewById(R.id.webView);
webview.getSettings().setJavaScriptEnabled(true);
webview.addJavascriptInterface(new JavaScriptInterface(), "HtmlViewer");
webview.setWebViewClient(new LoginWebView());
webview.loadUrl("EXAMPLE URL");
}
private class LoginWebView extends WebViewClient {
@SuppressLint({"JavascriptInterface"})
@Override
public void onPageFinished(WebView view, String url) {
view.loadUrl("javascript:(function(){" +
"\n" + " jQuery(document).ajaxComplete(function(event, request, settings){" +
"\n" + " var responseCode = JSON.parse(request.responseText).result.responseCode;" +
"\n" + " window.HtmlViewer.ajaxResponse(settings.url, responseCode);" +
"\n" + " });" +
"\n" + "})();";);
}
}
private class JavaScriptInterface {
@JavascriptInterface
public void ajaxResponse(String url, String responseCode) {
// Gets notified when Ajax finished loading
}
}
现在每次 Ajax 完成加载时,都会调用我的 ajaxResponse
方法。是否也可以在 UIWebView 中实现?
您可以使用evaluateJavaScript:completionHandler:
webView.evaluateJavaScript("yourJSfuncsToRunAJAX") { response, error in
//if error didn't occure do sth after js function finished
}
不幸的是,UIWebView 从 iOS 8 开始被弃用,因此您应该切换到 WKWebView。
来自 apple:"In apps that run in iOS 8 and later, use the WKWebView class instead of using UIWebView."
要在 ajax 完成时收到通知,您可以使用来自 的已接受回复。我在 javascript 和 swift.
之间使用了相同的桥接原则
希望对您有所帮助。
我终于找到了解决这个问题的方法。那里有很多解决方案,但它们都使用 jQuery,这似乎在 WKWebView
中不起作用。这是我的原始解决方案 JavaScript
.
这是 ViewController 实现,它让您在 WKWebView
中完成每个 AJAX 请求时得到通知:
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
文件:
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 请求时被调用。我路过 status
和 responseURL
,因为这正是我所需要的,但您也可以获得有关请求的更多信息。以下是所有可用属性和方法的列表:
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
我的解决方案受到@John Culviner 撰写的这个答案的启发:
是否可以在 Ajax 完成 UIWebView 加载时收到通知?在 Android 我可以这样做:
@SuppressLint("SetJavaScriptEnabled")
private void setUpWebView() {
webview = view.findViewById(R.id.webView);
webview.getSettings().setJavaScriptEnabled(true);
webview.addJavascriptInterface(new JavaScriptInterface(), "HtmlViewer");
webview.setWebViewClient(new LoginWebView());
webview.loadUrl("EXAMPLE URL");
}
private class LoginWebView extends WebViewClient {
@SuppressLint({"JavascriptInterface"})
@Override
public void onPageFinished(WebView view, String url) {
view.loadUrl("javascript:(function(){" +
"\n" + " jQuery(document).ajaxComplete(function(event, request, settings){" +
"\n" + " var responseCode = JSON.parse(request.responseText).result.responseCode;" +
"\n" + " window.HtmlViewer.ajaxResponse(settings.url, responseCode);" +
"\n" + " });" +
"\n" + "})();";);
}
}
private class JavaScriptInterface {
@JavascriptInterface
public void ajaxResponse(String url, String responseCode) {
// Gets notified when Ajax finished loading
}
}
现在每次 Ajax 完成加载时,都会调用我的 ajaxResponse
方法。是否也可以在 UIWebView 中实现?
您可以使用evaluateJavaScript:completionHandler:
webView.evaluateJavaScript("yourJSfuncsToRunAJAX") { response, error in
//if error didn't occure do sth after js function finished
}
不幸的是,UIWebView 从 iOS 8 开始被弃用,因此您应该切换到 WKWebView。 来自 apple:"In apps that run in iOS 8 and later, use the WKWebView class instead of using UIWebView."
要在 ajax 完成时收到通知,您可以使用来自
希望对您有所帮助。
我终于找到了解决这个问题的方法。那里有很多解决方案,但它们都使用 jQuery,这似乎在 WKWebView
中不起作用。这是我的原始解决方案 JavaScript
.
这是 ViewController 实现,它让您在 WKWebView
中完成每个 AJAX 请求时得到通知:
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
文件:
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 请求时被调用。我路过 status
和 responseURL
,因为这正是我所需要的,但您也可以获得有关请求的更多信息。以下是所有可用属性和方法的列表:
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
我的解决方案受到@John Culviner 撰写的这个答案的启发: