【问题标题】:Init from decoder in a protocol extension gives error "'self' used before 'self.init' call or assignment to 'self'"协议扩展中解码器的初始化给出了错误“在'self.init'调用或分配给'self'之前使用'self'”
【发布时间】:2020-09-26 13:24:27
【问题描述】:

我想解码协议的扩展:

protocol SettingsContentProtocol: Codable {
    var audioDelegate:AudioDelegate? { get set }
    var isPlaying: Bool { get set }
    var meditationTimes: [MeditationItem: TimeInterval] {get set}
    var intermediate: Int {get set}
    var contentsDuration: Float {get set}
    var durata:TimeInterval {get set}
    var parzialeDurata:TimeInterval {get set}
    var date: Date {get set}
    var hour: Int {get}
    var followDuration: TimeInterval {get set}

    func selectPeriod(item:MeditationItem)
    mutating func sliderMoved(item: MeditationItem, sliderPosition: Float)
    func calculateContentsDuration()->Float
    func tooShortTimeForContents(completion:@escaping ((Bool)->Void))
    func cleanQueue(items:[MPMediaItem])
    func selectRow(indexPath: IndexPath)
    func tableEdit(indexPath: IndexPath)
    func rowAt(indexPath: IndexPath, tableView: UITableView)->UITableViewCell
    mutating func adjustProgress(progress: TimeInterval)
    mutating func prepareMeditation()
    func meditationDetails()->Meditation
    func meditationMessage(final: Bool)->String
    func meditationTime()->String
}

与:

init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    isPlaying = try container.decode(Bool.self, forKey: .isPlaying)
    meditationTimes = try container.decode([MeditationItem: TimeInterval].self, forKey: .meditationTimes)
    intermediate=try container.decode(Int.self, forKey: .intermediate)
    contentsDuration=try container.decode(Float.self, forKey: .contentsDuration)
    durata=try container.decode(TimeInterval.self, forKey: .durata)
    parzialeDurata=try container.decode(TimeInterval.self, forKey: .parzialeDurata)
    date=try container.decode(Date.self, forKey: .date)
    followDuration=try container.decode(TimeInterval.self, forKey: .followDuration)
}

然而,当我编译时,我得到了每一行错误:

“在‘self.init’调用或赋值给‘self’之前使用‘self’”

我发现的所有示例似乎都与我的代码一致,但可能有什么问题?

【问题讨论】:

  • 你能显示minimal reproducible example吗?
  • 即返回错误的函数。它是协议扩展的一部分,我认为展示完整的类和协议没有什么意义,但如果你愿意,我当然可以这样做。
  • 由于您在协议中执行此操作,因此正如错误所说,您正在为属性分配值,但由于没有对象但也没有属性。初始化方法需要作用于从结构或类创建的对象
  • 您需要包含我需要的最少代码量,以便我可以复制并粘贴到 Xcode 中,或者我可以采取的最少步骤,以便查看您描述的错误.现在,您没有最小的可重现示例。 CodingKeys 来自哪里?
  • 您在此处展示的Codable 实现似乎是标准样板文件,可以由 Swift 合成。您不需要协议扩展。

标签: swift protocols codable


【解决方案1】:

问题是通过在协议中设置一个标准的 init() 来解决的

func encode(to encoder: Encoder) throws{
    var container = encoder.container(keyedBy: CodingKeys.self)
    try container.encode(isPlaying, forKey: .isPlaying)
    try container.encode(meditationTimes, forKey: .meditationTimes)
    try container.encode(intermediate, forKey: .intermediate)
    try container.encode(durata, forKey: .durata)
    try container.encode(parzialeDurata, forKey: .parzialeDurata)
    try container.encode(date, forKey: .date)
    try container.encode(followDuration, forKey: .followDuration)
}


init(from decoder: Decoder) throws {
    self.init()
    let container = try decoder.container(keyedBy: CodingKeys.self)
    isPlaying = try container.decode(Bool.self, forKey: .isPlaying)
    meditationTimes = try container.decode([MeditationItem: TimeInterval].self, forKey: .meditationTimes)
    intermediate=try container.decode(Int.self, forKey: .intermediate)
    durata=try container.decode(TimeInterval.self, forKey: .durata)
    parzialeDurata=try container.decode(TimeInterval.self, forKey: .parzialeDurata)
    date=try container.decode(Date.self, forKey: .date)
    followDuration=try container.decode(TimeInterval.self, forKey: .followDuration)
}

【讨论】:

  • 为什么首先需要自定义编码器和解码器?
  • 因为是编译器要求的。坦率地说,我认为您应该向 Apple 查询。
猜你喜欢
  • 1970-01-01
  • 2020-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-01
  • 1970-01-01
相关资源
最近更新 更多