swift - 接受并编码 Encodable 列表

标签 swift

我正在编写一个用于从 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/

相关文章:

ios - 为什么 Firebase 报告错误的屏幕数据?

Xcode 6 自动布局纵向和横向的不同约束

ios - Swift OpenGL ES 应用程序模板?

ios - EKEventEditViewController 显示有一个禁用的添加按钮

swift - 如何从 UITableViewCell 类调用 ViewController

ios - Swift中的关联对象,全局键是否实际产生特定实例?

ios - 为什么 AVAudioPlayer 在拔下耳机后继续播放?

ios - UIView 未以编程方式显示在 Swift 中的 UIViewcollection 中

swift - 如何在 Swift 中将 [Int8] 转换为 [UInt8]

ios - 登录或取消 firebase 社交登录后 View 错位 swift