首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >可编码的接受和编码列表

可编码的接受和编码列表
EN

Stack Overflow用户
提问于 2018-03-15 14:08:53
回答 2查看 335关注 0票数 0

我正在编写一个函数,用于从Swift调用JavaScript,并希望接受函数的名称和调用参数的列表。列表应该能够包含任何我可以转换成JSON的内容。

例如:

代码语言:javascript
复制
callJS(function: "console.log", withArgs: [1, "Hello"])

我天真地试图这样做:

代码语言:javascript
复制
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))")
}

不幸的是,这在运行时失败了,出现了以下致命错误:

致命错误:数组不符合Encodable,因为Encodable不符合它本身。您必须使用具体类型来编码或解码。

有没有办法让编译器从调用站点嵌入类型,以便Encodable知道该编码什么?

EN

回答 2

Stack Overflow用户

发布于 2018-03-15 14:14:34

一种解决方案是使用元组类型而不是Array。这样做的缺点是函数的独立性需要硬编码。

代码语言:javascript
复制
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

然后,可以简单地将其称为:

代码语言:javascript
复制
callJS(function: "console.log", withArgs: (1, "Hello"))
票数 0
EN

Stack Overflow用户

发布于 2018-03-15 14:23:29

我认为造成错误的原因是因为编译器被发送了令人困惑的信息,您试图同时传递一个StringInt,这样它就会抛出一个抖动,而不知道该如何处理生活。

当像这样使用时,它确实会起作用:

代码语言:javascript
复制
var array: Array<Codable> = [1, 2, "Hello"]

但是,如果函数中使用的对象都是相同类型的,那么让我们假设在该数组中的所有对象都是相同类型的,那么只需将函数更改为:

代码语言:javascript
复制
func callJS<Value: Encodable>(function: String, withArgs args: [Value])

但是,如果您希望在数组中使用多个对象,您可能希望查看我曾经编写过的这段代码(在这里发现的),其中我意识到了ArrayCodable的局限性,因此构建了这个AnyCodable,可以在使用Array<Any>Array<Codable>的地方使用。

像这样使用:

代码语言:javascript
复制
func callJS(function: String, withArgs args: [AnyCodable]) {
     let encoder = JSONEncoder()
     let data = try! encoder.encode(list)
     let jsonArgs = String(data: data, encoding: .utf8)

     executeJS("\(function)(...\(jsonArgs))")
}

callJS(function: "console.log", withArgs: [1, "Hello"])

注意:限制是它只在这种状态下与stdlib结构一起工作。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49301659

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档