【问题标题】:How to define variable with type of Codable?如何定义 Codable 类型的变量?
【发布时间】:2017-10-04 12:15:20
【问题描述】:

我想创建类型为 Codable 的变量。稍后在 JSONEncoder 类中使用它。我认为下面的代码应该可以正常工作,但它给了我错误:

无法使用(Codable) 类型的参数列表调用encode

如何声明 JSONEncoder 将正确使用的可编码变量?

struct Me: Codable {
    let id: Int
    let name: String
}

var codable: Codable? // It must be generic type, but not Me.

codable = Me(id: 1, name: "Kobra")

let data = try? JSONEncoder().encode(codable!)

Here 是类似的问题,如何使用函数传递 Codable。但我正在寻找如何使用变量(类变量)设置 Codable。

【问题讨论】:

  • 使用Any 而不是Codable
  • @LeoDabus 那么另一个问题是如何将它传递给 JSONEncoder?
  • 使用Me有什么问题?
  • 我仍然认为它是重复的。重新开放可能不会有什么不同。我将在此处发布链接作为参考stackoverflow.com/questions/45053060/…
  • @Ramis 这是不可能的——JSONEncoderJSONDecoder 需要具体类型,而 Codable 不是(类型为 Codable? 的变量称为 existential)。你能在这里展示你的用例吗?这个变量还能包含什么?

标签: json swift swift4 swift-protocols


【解决方案1】:

你的代码没问题,我们唯一需要关注的是Codable

Codable 是一个 typealias,它不会给你泛型类型。

JSONEncoder().encode(Generic confirming to Encodable).

所以,我修改了下面的代码,它可能对你有帮助..

protocol Codability: Codable {}

extension Codability {
    typealias T = Self
    func encode() -> Data? {
        return try? JSONEncoder().encode(self)
    }

    static func decode(data: Data) -> T? {
        return try? JSONDecoder().decode(T.self, from: data)
    }
}

struct Me: Codability
{
    let id: Int
    let name: String
}

struct You: Codability
{
    let id: Int
    let name: String
}

class ViewController: UIViewController
{
    override func viewDidLoad()
    {
        var codable: Codability
        codable = Me(id: 1, name: "Kobra")
        let data1 = codable.encode()

    codable = You(id: 2, name: "Kobra")
    let data2 = codable.encode()
}
}

【讨论】:

  • 你的解决方案救救我!
【解决方案2】:

我创建了和你一样的场景:

struct Me: Codable
{
    let id: Int
    let name: String
}

struct You: Codable
{
    let id: Int
    let name: String
}

class ViewController: UIViewController
{
    override func viewDidLoad()
    {
        var codable: Codable?

        codable = Me(id: 1, name: "Kobra")
        let data1 = try? JSONEncoder().encode(codable)

        codable = You(id: 2, name: "Kobra")
        let data2 = try? JSONEncoder().encode(codable)
    }
}

上面的代码没有给我任何错误。我唯一改变的是:

let data = try? JSONEncoder().encode(codable!)

我没有打开 codable 的包装,它工作正常。

【讨论】:

  • 编译不提供任何错误,但执行时会报错:致命错误:Optional 不符合 Encodable 因为 Encodable 不符合自身。您必须使用具体类型进行编码或解码。
  • 这就解释了。您需要使用具体类型。
【解决方案3】:

我用过这种方式,也许对你的情况也有帮助。

public protocol AbstractMessage: Codable {
  var id: Int { get } // you might add {set} as well
  var name: Int { get }
}

然后创建了一个方法:

public func sendMessage<T>(message: T) where T: AbstractMessage {
  let json = try! String(data: JSONEncoder().encode(message), encoding: .utf8)!
  ...
}

在这里我创建了一个通用协议,并将它作为泛型类型传递给我的函数。

【讨论】:

  • 你确定吗?那行得通吗?我写了同样的方法,但是有一个错误说“不能用'(Codable)'类型的参数列表调用'encode'”
  • @Sanju 这个目前在我正在开发的项目中使用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-24
  • 2011-11-11
相关资源
最近更新 更多