Apakah komunikasi sinkron antara JavaScript dan kode asli Swift/Obj-C dimungkinkan menggunakan WKWebView?
Ini adalah pendekatan yang telah saya coba dan gagal.
Pendekatan 1: Menggunakan pengendali skrip
WKWebView
Cara baru menerima pesan JS adalah dengan menggunakan metode delegasi userContentController:didReceiveScriptMessage:
yang dipanggil dari JS oleh window.webkit.messageHandlers.myMsgHandler.postMessage('What's the meaning of life, native code?')
Masalah dengan pendekatan ini adalah selama eksekusi metode delegasi asli, eksekusi JS tidak diblokir, jadi kami tidak dapat mengembalikan nilai dengan segera memanggil webView.evaluateJavaScript("something = 42", completionHandler: nil)
.
Contoh (JavaScript)
var something;
function getSomething() {
window.webkit.messageHandlers.myMsgHandler.postMessage("What's the meaning of life, native code?"); // Execution NOT blocking here :(
return something;
}
getSomething(); // Returns undefined
Contoh (Cepat)
func userContentController(userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage) {
webView.evaluateJavaScript("something = 42", completionHandler: nil)
}
Pendekatan 2: Menggunakan skema URL khusus
Di JS, pengalihan menggunakan window.location = "js://webView?hello=world"
memanggil metode WKNavigationDelegate
asli, tempat parameter kueri URL dapat diekstraksi. Namun, tidak seperti UIWebView, metode delegasi tidak memblokir eksekusi JS, jadi segera memanggil evaluateJavaScript
untuk meneruskan nilai kembali ke JS juga tidak berfungsi di sini.
Contoh (JavaScript)
var something;
function getSomething() {
window.location = "js://webView?question=meaning" // Execution NOT blocking here either :(
return something;
}
getSomething(); // Returns undefined
Contoh (Cepat)
func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler decisionHandler: (WKNavigationActionPolicy) -> Void) {
webView.evaluateJavaScript("something = 42", completionHandler: nil)
decisionHandler(WKNavigationActionPolicy.Allow)
}
Pendekatan 3: Menggunakan skema URL khusus dan IFRAME
Pendekatan ini hanya berbeda dalam cara window.location
ditugaskan. Alih-alih menetapkannya secara langsung, atribut src
dari iframe
kosong digunakan.
Contoh (JavaScript)
var something;
function getSomething() {
var iframe = document.createElement("IFRAME");
iframe.setAttribute("src", "js://webView?hello=world");
document.documentElement.appendChild(iframe); // Execution NOT blocking here either :(
iframe.parentNode.removeChild(iframe);
iframe = null;
return something;
}
getSomething();
Meskipun demikian, ini juga bukan solusi, ini menggunakan metode asli yang sama seperti Pendekatan 2, yang tidak sinkron.
Lampiran: Cara mencapainya dengan UIWebView lama
Contoh (JavaScript)
var something;
function getSomething() {
// window.location = "js://webView?question=meaning" // Execution is NOT blocking if you use this.
// Execution IS BLOCKING if you use this.
var iframe = document.createElement("IFRAME");
iframe.setAttribute("src", "js://webView?question=meaning");
document.documentElement.appendChild(iframe);
iframe.parentNode.removeChild(iframe);
iframe = null;
return something;
}
getSomething(); // Returns 42
Contoh (Cepat)
func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
webView.stringByEvaluatingJavaScriptFromString("something = 42")
}
var isTwitterInstalled = isInstalled('twitter');
. Jika Anda hanya menerima panggilan asinkron, Anda harus membaginya menjadi dua fungsi; satu yang Anda panggil dari JavaScript dan satu lagi yang Anda panggil dari kode asli, meneruskan hasilnya. - person paulvs   schedule 23.02.2015window
? - person Steve Landey   schedule 28.03.2015var something;
sebenarnya berlebihan karena injeksi dari kode asli membuatsomething
sebagai global ketika menetapkan nilainya. - person paulvs   schedule 30.03.2015var something
membayangi global. Itu tidak berlebihan, itu bug. - person Steve Landey   schedule 30.03.2015var something;
tidak ada di dalam fungsi apa pun, yaitu dalam lingkup global, ini akan membuat variabel global bernamasomething
(setara denganwindow.something = undefined;
). Kemudian, kode asli menetapkan42
ke variabel globalwindow.something
(dan jika global tidak ada, kode tersebut akan membuatnya terlebih dahulu, lalu menetapkan nilainya). Jadi, apakah kita membuat deklarasisomething
terlebih dahulu atau tidak, itu dibuat oleh kode asli, bukan? - person paulvs   schedule 31.03.2015window.location
atauiframe
, bisakah saya menggunakan ajax saja? - person Maria   schedule 16.10.2018