swift 与 Javascriptcore 的异步通信
Async communication of swift and Javascriptcore
我想在 Web 视图之外使用 WKWebView 提供的异步功能。
JS 上下文选项不提供异步功能。
在WKWebView中,我的逻辑是这样写的
func swiftFunc1() {
webView.evaluateJavaScript("jsFunc1(), completionHandler: nil)
}
在 javascript 代码中我 post 一条消息到 swift
function jsFunc1() {
window.webkit.messageHandlers.myMsg.postMessage("call swiftFunc2");
}
swift 代码然后可以调用适当的 JS 回调作为处理消息的一部分。
但这取决于 webview 是前景视图。如果我想使用独立于 webview 的 JS 逻辑,可以选择 JSContext。我尝试关注
func swiftFunc1() {
myCtxt = JSContext()
exportedToJS = exportToJS() //confirms to JSExport and uses @objc
myCtxt.setObject(exportedToJS.self, forKeyedSubscript: "swiftIface")
myFunc = myCtxt.objectForKeyedSubscript("jsFunc1")
myFunc.callWithArguments(nil)
}
现在在 javascript 代码中,我无法 post 向 swift 发送消息。如果我尝试按如下方式调用 swift 函数,代码将永远卡住。
function jsFunc1() {
swiftIface.swiftFunc2() // This creates a deadklock
}
如果没有 "returning" 从被调用的 Javascript 函数 jsFunc1() 中,我如何实现以下任一目标?
要么 post 向 swift 发送消息,以便它可以采取适当的行动
或调用 swift 函数以便采取适当的操作
如果你不希望你的 javscript 在执行后终止,我的理解对吗?
如果我理解错了,也许下面的帮助(我不在家 Mac 测试,但如果您按如下方式修改代码,也许它会起作用)。
选项 1:块
swiftFunc1 可能如下所示:
func swiftFunc1() {
myCtxt = JSContext()
myCtxt.setObject(unsafeBitCast(swiftFunc2, AnyObject.self), forKeyedSubscript: "swiftFunc2")
exportedToJS = exportToJS() //confirms to JSExport and uses @objc
myCtxt.evaluateScript("swiftFunc2()")
}
你的 swiftFunc2 看起来像这样:
let swiftFunc2: @convention(block) Void -> Void = {
// do something here
}
您的 JS 代码将如下所示:
function jsFunc1() {
swiftFunc2();
}
选项 2:JSExport
您有一个导出的 class 可供所有 javascript:
访问
import Foundation
import JavaScriptCore
@objc class JavascriptHandler: NSObject, JavascriptHandlerExport {
let context: JSContext = JSContext()
init () {
context.setObject(self, forKeyedSubscript: "MyJSHandler") // set the object name for self accessible in javascript code
}
func swiftFunc1() {
context.evaluateScript("MyJSHandler.swiftFunc2();")
}
func swiftFunc2 () {
// do something here
}
}
您的导出协议 class.Here 您必须声明要与 Javascript 一起使用的所有属性和方法。
import Foundation
import JavaScriptCore
@objc protocol JavascriptHandlerExport: JSExport {
func swiftFunc2 ( ) -> Void
}
有了这个,您应该可以从 javascript 调用一个函数并让它继续。
您现在可以从 Javascript 访问 class JavascriptHandler 的函数,在这个例子中是这样的:
MyJSHandler.swiftFunc2();
如果你想将你的 WebView 所在的 class 与你的 JS 逻辑所在的那个分开,那应该也不是问题。您还应该能够将块语法与 JSExport 方法结合起来。
如果working/behaving不符合要求,请告诉我。
我想在 Web 视图之外使用 WKWebView 提供的异步功能。 JS 上下文选项不提供异步功能。
在WKWebView中,我的逻辑是这样写的
func swiftFunc1() {
webView.evaluateJavaScript("jsFunc1(), completionHandler: nil)
}
在 javascript 代码中我 post 一条消息到 swift
function jsFunc1() {
window.webkit.messageHandlers.myMsg.postMessage("call swiftFunc2");
}
swift 代码然后可以调用适当的 JS 回调作为处理消息的一部分。
但这取决于 webview 是前景视图。如果我想使用独立于 webview 的 JS 逻辑,可以选择 JSContext。我尝试关注
func swiftFunc1() {
myCtxt = JSContext()
exportedToJS = exportToJS() //confirms to JSExport and uses @objc
myCtxt.setObject(exportedToJS.self, forKeyedSubscript: "swiftIface")
myFunc = myCtxt.objectForKeyedSubscript("jsFunc1")
myFunc.callWithArguments(nil)
}
现在在 javascript 代码中,我无法 post 向 swift 发送消息。如果我尝试按如下方式调用 swift 函数,代码将永远卡住。
function jsFunc1() {
swiftIface.swiftFunc2() // This creates a deadklock
}
如果没有 "returning" 从被调用的 Javascript 函数 jsFunc1() 中,我如何实现以下任一目标?
要么 post 向 swift 发送消息,以便它可以采取适当的行动
或调用 swift 函数以便采取适当的操作
如果你不希望你的 javscript 在执行后终止,我的理解对吗?
如果我理解错了,也许下面的帮助(我不在家 Mac 测试,但如果您按如下方式修改代码,也许它会起作用)。
选项 1:块
swiftFunc1 可能如下所示:
func swiftFunc1() {
myCtxt = JSContext()
myCtxt.setObject(unsafeBitCast(swiftFunc2, AnyObject.self), forKeyedSubscript: "swiftFunc2")
exportedToJS = exportToJS() //confirms to JSExport and uses @objc
myCtxt.evaluateScript("swiftFunc2()")
}
你的 swiftFunc2 看起来像这样:
let swiftFunc2: @convention(block) Void -> Void = {
// do something here
}
您的 JS 代码将如下所示:
function jsFunc1() {
swiftFunc2();
}
选项 2:JSExport 您有一个导出的 class 可供所有 javascript:
访问import Foundation
import JavaScriptCore
@objc class JavascriptHandler: NSObject, JavascriptHandlerExport {
let context: JSContext = JSContext()
init () {
context.setObject(self, forKeyedSubscript: "MyJSHandler") // set the object name for self accessible in javascript code
}
func swiftFunc1() {
context.evaluateScript("MyJSHandler.swiftFunc2();")
}
func swiftFunc2 () {
// do something here
}
}
您的导出协议 class.Here 您必须声明要与 Javascript 一起使用的所有属性和方法。
import Foundation
import JavaScriptCore
@objc protocol JavascriptHandlerExport: JSExport {
func swiftFunc2 ( ) -> Void
}
有了这个,您应该可以从 javascript 调用一个函数并让它继续。 您现在可以从 Javascript 访问 class JavascriptHandler 的函数,在这个例子中是这样的:
MyJSHandler.swiftFunc2();
如果你想将你的 WebView 所在的 class 与你的 JS 逻辑所在的那个分开,那应该也不是问题。您还应该能够将块语法与 JSExport 方法结合起来。
如果working/behaving不符合要求,请告诉我。