【问题标题】:What is the simplest way to instantiate a new Codable object in Swift?在 Swift 中实例化一个新的 Codable 对象的最简单方法是什么?
【发布时间】:2019-01-22 05:40:38
【问题描述】:

我有一个 Codable 类:

class Task: Codable {
    var name: String
}

当我尝试实例化它时:

let newTask = Task()
allTasks.append(newTask)

它给了我错误:

调用中的参数“from”缺少参数

我想要的只是将一个新对象(newTask)插入到一个数组中。最简单的方法是什么?

【问题讨论】:

  • 如果您不使用任何编码键,为什么要使用可编码??
  • 你有什么理由不接受我的回答吗?

标签: swift codable


【解决方案1】:

你可以从 NSObject 继承初始化器:

class Task: NSObject, Codable {
    var name: String = ""
}

let newTask = Task()

如果您不想继承 NSObject,那么只需创建自己的初始化程序:

class Task: Codable {
    var name: String?

    init() {

    }
}

如果您不想让name 成为可选(或将其设置为默认值),则必须在 init() 中对其进行初始化,例如:

class Task: Codable {
    var name: String

    init(withName name: String) {
        self.name = name
    }
}
let newTask = Task(withName: "ikevin8me")

【讨论】:

  • 好的,请查看编辑后的回复。 name 变量需要一个默认值。否则,在分配 self 之前它是未启动的。
  • 好的,这使它工作,但这确实不是最好的解决方案。它不必要地带来了NSObject 和所有的Objective-C 包袱。并且默认 name 为空字符串是非常非 Swifty 的。
  • 然后编写你自己的初始化器。
  • 我添加了一个没有继承NSObject的例子。
  • 如果你不想要一个空字符串,你可以让这个字符串是可选的,或者你必须在 init() 中初始化它。我更改了第二个示例以使其成为可选。
【解决方案2】:

另一个解决方案是使用struct

struct Task: Codable {
    var name: String
}

let task = Task(name: "myname")

【讨论】:

    【解决方案3】:

    您的 Task 类没有提供自己的初始化程序,因此它获取在 Codable 协议中定义的初始化程序(它从 Decodable 协议中获得)。

    要么添加您自己的显式init,它采用name 参数,要么将您的类更改为结构。无论哪种方式,您都需要通过传入名称值来创建Task,以便可以初始化name 属性。

    这些都没有解决您发布的代码没有使用Codable 的事实,因此您的类(或结构)可能不需要符合Codable。

    【讨论】:

      【解决方案4】:

      Task 类不提供任何初始化器来初始化对象,这就是它从 Codable 协议获取初始化器的原因,提供您自己的初始化器来初始化对象。

      用法:

      1.带类

      class Task: Codable {
          var name: String
          init(_ name : String) {
              self.name = name
          }
      }
      
      var task = Task("Jarvis")
      

      2.带结构:

      struct Task: Codable {
          var name: String
      }
      
      let task = Task(name: "jarvis")
      

      【讨论】:

      • 为什么要隐式解包name 属性?不要不必要地这样做。
      • @rmaddy 我希望它能正确初始化。
      • 已更新...你能说出为什么你这么害怕'!' ;)
      • 我不怕。我向您指出,当它不合适时,您不应该使用它。这里不需要。
      • @JarvisTheAvenger 有a few very specific situations where you should use implicitly unwrapped optionals。大多数情况下,要么是不必要的,要么可能会导致您的应用崩溃,这似乎是“害怕”的合理事情。
      【解决方案5】:

      我不会为属性分配默认值,而是实现预期的 init 方法和不带任何参数的便利变体,或者具有创建“空”任务的工厂方法

      这是两个选项的代码

      class Task: Codable {
          var name: String
      
          init(_ name: String) {
              self.name = name
          }
      
          convenience init() {
              self.init("")
          }
      
          static func emptyTask() -> Task {
              return Task("")
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2012-03-09
        • 2010-12-29
        • 1970-01-01
        • 1970-01-01
        • 2015-06-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多