我正在使用JavascriptCode框架编写iOS应用程序(使用xcode 7.3和swift 2.2)。从swift调用javascript方法是完美的,但是当我从javascript调用swift方法时,xcode只显示一个“加载”类型的符号,没有任何反应。我需要“强制退出”xcode才能摆脱这种状态。 我已关注https://www.raywenderlich.com/124075/javascriptcore-tutorial和http://nshipster.com/javascriptcore/,我正在尝试非常简单的电话。
有没有人遇到过这种问题?
我的快速代码如下:
@objc protocol WindowJSExports : JSExport {
var name: String { get set }
func getName() -> String
static func createWindowWithName(name: String) -> WindowJS
}
@objc class WindowJS : NSObject, WindowJSExports {
dynamic var name: String
init(name: String) {
self.name = name
}
class func createWindowWithName(name: String) -> WindowJS {
return WindowJS(name: name)
}
func getName() -> String {
NSLog("getName called from JS context")
return "\(name)"
}
}
我正在按如下方式初始化上下文:
runContext = JSContext()
runContext.name = "test_Context"
windowToJs = WindowJS(name: "test")
runContext.setObject(windowToJs.self, forKeyedSubscript: "WindowJS")
如果我用上面的代码替换上面代码中的最后两行而没有实例化它,代码就无法加载。
runContext.setObject(WindowJS.self, forKeyedSubscript: "WindowJS")
javascript代码就像
一样简单function check() {
return WindowJS.getName()
}
我确实在JS函数检查中看到了断点,当调用WindowJS.getName时,xcode只是没有响应。
答案 0 :(得分:2)
你正在创建一个死锁,因为你从Swift调用JavaScript回到Swift。我不确定它为什么会出现死锁,但我最近在Mac上遇到了与WKWebView类似的问题。
您需要将其解耦并使通信异步。这显然意味着在这种情况下你不能简单地从JS函数中返回一个值。
要解耦,您可以使用setTimeout
延迟当前runloop迭代中JavaScript函数需要完成的工作来解除死锁:
function myFunction() {
setTimeout(function() {
// The actual work is done here.
// Call the Swift part here.
}, 0);
}
整个本地↔︎JavaScript通信非常非常棘手。如果可以,请避免使用它。有一个名为XWebView的项目可以帮助你,因为它试图缓解两个世界之间的桥梁。
答案 1 :(得分:2)
可以通过将以下代码添加到我的swift函数来解决setTimeout。
let setTimeout: @convention(block) (JSValue, Int) -> () =
{ callback, timeout in
let timeVal = Int64(timeout)
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, timeVal), dispatch_get_main_queue(), { callback.callWithArguments(nil)})
}
要将此本机代码公开给JS上下文,我还添加了以下内容。
runContext.setObject(unsafeBitCast(setTimeout, AnyObject.self), forKeyedSubscript: "setTimeout")
然后事情很好。