我正在编写一个用于从 Swift 调用 JavaScript 的函数,并且希望接受函数的名称和要调用的参数列表。该列表应该能够包含我可以转换为 JSON 的任何内容。
例如
callJS(function: "console.log", withArgs: [1, "Hello"])
我的天真尝试是这样的:
func callJS(function: String, withArgs args: [Encodable]) {
let encoder = JSONEncoder()
let data = try! encoder.encode(list)
let jsonArgs = String(data: data, encoding: .utf8)
executeJS("\(function)(...\(jsonArgs))")
}
不幸的是,在运行时失败并出现以下 fatal error :
Fatal error: Array does not conform to Encodable because Encodable does not conform to itself. You must use a concrete type to encode or decode.
有什么方法可以让编译器嵌入调用站点中的类型,以便 Encodable
知道要编码什么?
最佳答案
一种解决方案是使用元组类型而不是数组
。这样做的缺点是函数的数量需要进行硬编码。
func callJS(function: String) {
executeJS("\(function)()")
}
func callJS<A: Encodable>(function: String, withArg arg: A) {
let a = try! String(data: self.encoder.encode([arg]), encoding: .utf8)!
executeJS("\(function)(\(a))")
}
func callJS<A: Encodable, B: Encodable>(function: String, withArgs args: (A, B)) {
let a = try! String(data: self.encoder.encode([args.0]), encoding: .utf8)!
let b = try! String(data: self.encoder.encode([args.1]), encoding: .utf8)!
executeJS("\(function)(\(a),\(b))")
}
func callJS<A: Encodable, B: Encodable, C: Encodable>(function: String, withArgs args: (A, B, C)) {
let a = try! String(data: self.encoder.encode([args.0]), encoding: .utf8)!
let b = try! String(data: self.encoder.encode([args.1]), encoding: .utf8)!
let c = try! String(data: self.encoder.encode([args.2]), encoding: .utf8)!
executeJS("\(function)(\(a),\(b),\(c))")
}
func callJS<A: Encodable, B: Encodable, C: Encodable, D: Encodable>(function: String, withArgs args: (A, B, C, D)) {
let a = try! String(data: self.encoder.encode([args.0]), encoding: .utf8)!
let b = try! String(data: self.encoder.encode([args.1]), encoding: .utf8)!
let c = try! String(data: self.encoder.encode([args.2]), encoding: .utf8)!
let d = try! String(data: self.encoder.encode([args.3]), encoding: .utf8)!
executeJS("\(function)(\(a),\(b),\(c),\(d))")
}
// and so on for each arity that you need to support
然后可以简单地调用它:
callJS(function: "console.log", withArgs: (1, "Hello"))
关于swift - 接受并编码 Encodable 列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49301659/