简体   繁体   English

如何从Swift调用JavaScript

[英]How to call javascript from swift

I would like to extend my spreadsheet app with some user-defined macros. 我想用一些用户定义的宏扩展电子表格应用程序。 It seems to be a good idea to use javascript ... 使用javascript似乎是一个好主意...

It found a "small issue" (I am very unfamiliar with javascript at all) 它发现了一个“小问题”(我完全不熟悉javascript)

import JavaScriptCore

let context = JSContext()!
context.exceptionHandler = { context, exception in
    print("exception:", exception?.toString() ?? "")
}

context.evaluateScript(
    """
    foo = function(a, b) {
        return a + b
    }
    """
)
context.evaluateScript("foo(1, 2)") // 3
context.objectForKeyedSubscript("foo")?.call(withArguments: [1,2]) // 3

context.evaluateScript(
    """
    Foo = function() {}
    Foo.foo = function(a, b) {
        return a + b
    }
    """
)
context.evaluateScript("Foo.foo(1, 2)") // 3

// exception.  TypeError: undefined is not an object
context.objectForKeyedSubscript("Foo.foo")?.call(withArguments: [1, 2]) // Foo.foo is undefined ?????

If Foo.foo is undefined, how it could run just one line earlier? 如果Foo.foo是未定义的,它怎么能只运行一行呢?

finally I found a solution ... 终于我找到了解决方案...

context.objectForKeyedSubscript("Foo")?.objectForKeyedSubscript("foo")?.call(withArguments: [1, 2]) // 3

or better ... 或更好 ...

extension JSContext {
    func objectForKeySubscript(_ dotted: String) -> JSValue! {
        var iterator = dotted.split(separator: ".").makeIterator()
        var jsValue = self.objectForKeyedSubscript(iterator.next())
        while let str = iterator.next() {
            jsValue = jsValue?.objectForKeyedSubscript(str)
        }
        return jsValue
    }
}
context.objectForKeySubscript("Foo.foo")?.call(withArguments: [1, 2])

and finaly I found, that 最后我发现

context.evaluateScript("Foo.foo")?.call(withArguments: [1, 2])

works without any trouble ... :-) 可以正常工作... :-)

You tried .call(withArguments . But I think this works with Function.prototype.call() that requires two arguments(object and arguments). For more info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call 您尝试了.call(withArguments ,但是我认为这可以与Function.prototype.call() ,该Function.prototype.call()需要两个参数(对象和参数)。有关更多信息: https : //developer.mozilla.org/en-US/docs/网络/ JavaScript的/参考/ Global_Objects /功能/通话

This works 这有效

context.objectForKeyedSubscript("Foo")?.invokeMethod("foo", withArguments: [1, 2])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM