Init from decoder in a protocol extension gives error "'self' used before 'self.init' call or assignment to 'self'"

521 Views Asked by At

I would like to decode a an extension of protocol:

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
}

with:

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)
}

Yet, when I compile I get on each line error:

"'self' used before 'self.init' call or assignment to 'self'"

All the examples I found seem to agree with my code, what might be wrong instead?

1

There are 1 best solutions below

2
On

The issue is fixed by setting a standard init() in the protocol each adopting struct of course adopts, and I called it from the init(from:) as follows:

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)
}