【问题标题】:Async communication of swift and Javascriptcoreswift和Javascriptcore的异步通信
【发布时间】:2016-07-09 15:26:28
【问题描述】:

我想在 Web 视图之外使用 WKWebView 提供的异步功能。 JS Context 选项不提供异步功能。

在 WKWebView 中,我的逻辑如下。

func swiftFunc1() {
   webView.evaluateJavaScript("jsFunc1(), completionHandler: nil)
}

在 javascript 代码中我向 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 代码中,我无法向 swift 发布消息。如果我尝试如下调用 swift 函数,代码会永远卡住。

function jsFunc1() {
   swiftIface.swiftFunc2() // This creates a deadklock
 }

如何在不从被调用的 Javascript 函数 jsFunc1() 中“返回”的情况下实现以下任一功能?

  1. 要么向 swift 发布消息,以便它可以采取适当的措施

  2. 或调用 swift 函数以便采取适当的措施

【问题讨论】:

    标签: swift wkwebview javascriptcore


    【解决方案1】:

    如果您不希望您的 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 您有一个可供所有 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
      }
    }
    

    导出类的协议。在这里,您必须声明要与 Javascript 一起使用的所有属性和方法。

    import Foundation
    import JavaScriptCore
    @objc protocol JavascriptHandlerExport: JSExport {
      func swiftFunc2 ( ) -> Void
    }
    

    有了这个,你应该可以从 javascript 调用一个函数并让它继续。 您现在可以在本例中像这样从 Javascript 访问类 JavascriptHandler 的功能:

    MyJSHandler.swiftFunc2();
    

    如果您想将 WebView 所在的类与 JS 逻辑所在的类分开,这也不成问题。您还应该能够将块语法与 JSExport 方法结合起来。

    如果它没有按预期工作/行为,请告诉我。

    【讨论】:

    • 感谢您的回答。但这是否意味着我应该只使用块/闭包来解决这个问题? JSExport 无法处理这种调用顺序,是吗?
    • JSExport 应该也可以。也许明天有时间我可以举个例子。
    • 期待!
    • 你觉得这可能吗?
    • 我之前尝试过这种排列方式,发现XCode在出现这样的循环时会直接挂掉。见stackoverflow.com/questions/37908059/…
    猜你喜欢
    • 1970-01-01
    • 2011-06-08
    • 2017-05-21
    • 2015-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-23
    • 1970-01-01
    相关资源
    最近更新 更多