使用 JavascriptCore 和 JSContext 从 javascript 调用本机 Swift 代码

Calling native Swift code from javascript using JavascriptCore and JSContext

我正在尝试在 JavaScript 中使用本机 Swift 代码,运行 在 JSContext 中。

例如,我在 Swift 中实现了这个 class:

class Greeter: NSObject {

   public func greet() -> String {
     return "Hello World!"
   }

   public func greetMe(_ name: String) -> String {
     return "Hello, " + name + "!"
   }
}

然后我使用 JSContext 来 运行 一个 javascript 代码:

let context =  JSContext()!
context.setObject(Greeter.self, forKeyedSubscript: "Greeter" as (NSCopying & NSObjectProtocol))

// Try my native functions:
let jsv1 = context.evaluateScript("Greeter.greet()")!
let jsv2 = context.evaluateScript("Greeter.greetMe(\"Jon Arbuckle\")")!

print("Greeter.greet() =  \(jsv1)") // prints Greeter.greet() = undefined
print("Greeter.greatMe(\"Jon Arbuckle\") = \(jsv2)") // prints Greeter.greetMe("Jon Arbuckle") = undefined

无法弄清楚我做错了什么。

我们不应该忘记的一件事是通过符合 JSExport 协议来公开方法或属性。

@objc protocol GreeterJSExports: JSExport {
   func greet() -> String
   func greetMe(_ name: String) -> String
   static func getInstance() -> Greeter
   //any other properties you may want to export to JS runtime 
   //var greetings: String {get set}
}

遵守此协议

class Greeter: NSObject, GreeterJSExports {
   public func greet() -> String {
     return "Hello World!"
   }

   public func greetMe(_ name: String) -> String {
     return "Hello, " + name + "!"
   }
   class func getInstance() -> Greeter {
     return Greeter()
   }
}

像往常一样在 JSContext 中设置对象

let context = JSContext()
context?.setObject(Greeter.self, forKeyedSubscript: "Greeter" as (NSCopying & NSObjectProtocol))
let jsValue1 = context?.evaluateScript("(function(){ var greeter = Greeter.getInstance(); return greeter.greet()})()")
let jsValue2 = context?.evaluateScript("(function(){ var greeter = Greeter.getInstance(); return greeter.greetMe('rikesh')})()")
print(jsValue1!)
print(jsValue2!)

记住,上面的方法是实例方法。我们需要对象来调用它。 Swift 不暴露 init(), 因此,我向 return 一个实例添加了一个 getInstance 方法。