การสื่อสารแบบซิงโครนัสระหว่าง JavaScript และโค้ดเนทิฟ Swift / Obj-C เป็นไปได้โดยใช้ WKWebView หรือไม่
นี่คือแนวทางที่ฉันได้ลองและล้มเหลว
วิธีที่ 1: การใช้ตัวจัดการสคริปต์
วิธีใหม่ในการรับข้อความ JS ของ WKWebView
คือการใช้วิธีการมอบหมาย userContentController:didReceiveScriptMessage:
ซึ่งถูกเรียกใช้จาก JS โดย window.webkit.messageHandlers.myMsgHandler.postMessage('What's the meaning of life, native code?')
ปัญหาของวิธีนี้คือในระหว่างดำเนินการตามวิธีมอบหมายดั้งเดิม การดำเนินการ JS จะไม่ถูกบล็อก ดังนั้นเราจึงไม่สามารถส่งคืนค่าได้ โดยเรียกใช้ webView.evaluateJavaScript("something = 42", completionHandler: nil)
ทันที
ตัวอย่าง (จาวาสคริปต์)
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
ตัวอย่าง (สวิฟท์)
func userContentController(userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage) {
webView.evaluateJavaScript("something = 42", completionHandler: nil)
}
วิธีที่ 2: การใช้รูปแบบ URL ที่กำหนดเอง
ใน JS การเปลี่ยนเส้นทางโดยใช้ window.location = "js://webView?hello=world"
จะเรียกใช้เมธอด WKNavigationDelegate
ดั้งเดิม ซึ่งสามารถแยกพารามิเตอร์การสืบค้น URL ได้ อย่างไรก็ตาม ต่างจาก UIWebView ตรงที่วิธีการมอบสิทธิ์ไม่ได้บล็อกการดำเนินการ JS ดังนั้นการเรียกใช้ evaluateJavaScript
เพื่อส่งค่ากลับไปยัง JS ทันทีจึงไม่ทำงานที่นี่เช่นกัน
ตัวอย่าง (จาวาสคริปต์)
var something;
function getSomething() {
window.location = "js://webView?question=meaning" // Execution NOT blocking here either :(
return something;
}
getSomething(); // Returns undefined
ตัวอย่าง (สวิฟท์)
func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler decisionHandler: (WKNavigationActionPolicy) -> Void) {
webView.evaluateJavaScript("something = 42", completionHandler: nil)
decisionHandler(WKNavigationActionPolicy.Allow)
}
วิธีที่ 3: การใช้รูปแบบ URL ที่กำหนดเองและ IFRAME
วิธีการนี้แตกต่างเฉพาะกับวิธีการกำหนด window.location
เท่านั้น แทนที่จะกำหนดโดยตรง จะใช้แอตทริบิวต์ src
ของ iframe
ที่ว่างเปล่า
ตัวอย่าง (จาวาสคริปต์)
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();
อย่างไรก็ตาม สิ่งนี้ก็ไม่ใช่วิธีแก้ปัญหาเช่นกัน แต่จะเรียกใช้วิธีเนทิฟแบบเดียวกับวิธีที่ 2 ซึ่งไม่ซิงโครนัส
ภาคผนวก: วิธีบรรลุเป้าหมายนี้ด้วย UIWebView แบบเก่า
ตัวอย่าง (จาวาสคริปต์)
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
ตัวอย่าง (สวิฟท์)
func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
webView.stringByEvaluatingJavaScriptFromString("something = 42")
}
var isTwitterInstalled = isInstalled('twitter');
หากคุณมีเพียงการโทรแบบอะซิงโครนัส คุณจะต้องแยกออกเป็นสองฟังก์ชัน อันหนึ่งที่คุณโทรจาก JavaScript และอีกอันที่คุณโทรจากโค้ดเนทีฟโดยส่งผ่านผลลัพธ์ - person paulvs   schedule 23.02.2015window
แล้วหรือยัง? - person Steve Landey   schedule 28.03.2015var something;
นั้นไม่จำเป็นจริง ๆ เพราะการฉีดจากโค้ดเนทีฟจะสร้างsomething
เป็นโกลบอลเมื่อมันกำหนดค่าของมัน - person paulvs   schedule 30.03.2015var something
เงาทั่วโลก มันไม่ได้ฟุ่มเฟือย มันเป็นข้อผิดพลาด - person Steve Landey   schedule 30.03.2015var something;
ไม่อยู่ในฟังก์ชันใด ๆ เช่นมันอยู่ในขอบเขตส่วนกลาง มันจะสร้างตัวแปรส่วนกลางที่เรียกว่าsomething
(เทียบเท่ากับwindow.something = undefined;
) จากนั้น โค้ดเนทิฟจะกำหนด42
ให้กับตัวแปรโกลบอลwindow.something
(และหากไม่มีโกลบอลอยู่ มันจะสร้างตัวแปรขึ้นมาก่อน จากนั้นจึงกำหนดค่าของมัน) ดังนั้นไม่ว่าเราจะสร้าง Decansomething
ไว้ล่วงหน้าหรือไม่ก็ตาม มันถูกสร้างขึ้นด้วยโค้ดเนทีฟใช่ไหม? - person paulvs   schedule 31.03.2015window.location
หรือiframe
ฉันสามารถใช้ ajax ได้ไหม - person Maria   schedule 16.10.2018