Получить обратный вызов, когда UIWebView заканчивает загрузку Ajax - PullRequest
0 голосов
/ 30 августа 2018

Можно ли получить уведомление, когда 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?

Ответы [ 3 ]

0 голосов
/ 30 августа 2018

К сожалению, UIWebView устарела с iOS 8, поэтому вам следует переключиться на WKWebView. От apple : «В приложениях, работающих в iOS 8 и более поздних версиях, используйте класс WKWebView вместо UIWebView.»

Чтобы получить уведомление о завершении ajax, вы можете использовать принятый ответ от здесь . Я использовал тот же принцип для соединения между JavaScript и Swift.

Надеюсь, это поможет.

0 голосов
/ 21 сентября 2018

Я наконец нашел решение этой проблемы. Существует множество решений, но все они используют jQuery, который, похоже, не работает в WKWebView. Вот мое решение в raw JavaScript.

Вот реализация ViewController, которая позволяет получать уведомления о каждом запросе AJAX, выполненном в WKWebView:

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: https://stackoverflow.com/a/27363569/3448282

0 голосов
/ 30 августа 2018

Вы можете использовать evaluateJavaScript:completionHandler:

webView.evaluateJavaScript("yourJSfuncsToRunAJAX") { response, error in
    //if error didn't occure do sth after js function finished
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...