Swift 带有自定义编码器和解码器的结构不能符合 'Encodable'

Swift struct with custom encoder and decoder cannot conform to 'Encodable'

[编辑以提供最小的可重现示例]

这是没有非相关变量和函数的完整结构

InstrumentSet.swift

import Foundation

struct InstrumentsSet: Identifiable, Codable {
        
    private enum CodingKeys: String, CodingKey {
        case name = "setName"
        case tracks = "instrumentsConfig"
    }
    
    var id: String { name }
    var name: String
    var tracks: [Track]
}

Track.swift

import Foundation

extension InstrumentsSet {
    
    struct Track: Identifiable, Encodable {
        
        private enum TrackKeys: String, CodingKey {
            case id = "trackId"
            case effects
        }
        
        let id: String
        var effects: [Effect]?
    }
}

extension InstrumentsSet.Track: Decodable {
    
    init(from decoder: Decoder) throws {
        
        let container = try decoder.container(keyedBy: TrackKeys.self)
        id = try container.decode(String.self, forKey: .id)
        effects = try container.decodeIfPresent([Effect].self, forKey: .effects)
    }
}

Effect.swift

import Foundation
import AudioKit
import SoundpipeAudioKit

extension InstrumentsSet.Track {
    
    enum Effect: Decodable {
        
        private enum EffectKeys: String, CodingKey {
            case effectType = "effectName"
            case cutoffFrequency
            case resonance
        }
        
        case lowPassFilter(LowPassFilterEffect)
        
        init(from decoder: Decoder) throws {
            let container = try decoder.container(keyedBy: EffectKeys.self)
            let effectType = try container.decode(Effect.EffectType.self, forKey: .effectType)
            switch effectType {
            case .lowPassFilter:
                let cutOffFrequency = try container.decode(ValueAndRange.self, forKey: .cutoffFrequency)
                let resonance = try container.decode(ValueAndRange.self, forKey: .resonance)
                self = .lowPassFilter(LowPassFilterEffect(cutOffFrequency: cutOffFrequency, resonance: resonance))
            
            default:
                fatalError("Not implemented!")
            }
        }
    }
}

extension InstrumentsSet.Track.Effect {
    
    enum EffectType: String, Decodable {
        case lowPassFilter
    }
}

extension InstrumentsSet.Track.Effect: Encodable {

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: EffectKeys.self)

        //FIXME: This is the location of the error: Type 'ValueAndRange.Type' cannot conform to 'Encodable'
        try container.encode(ValueAndRange.self, forKey: .cutoffFrequency)

    }
}

问题是ValueAndRange.self不符合Encodable 我遵循了多个示例来实现此实现:

import Foundation
import AudioKit

struct ValueAndRange: Encodable {
    
    private enum ValueRangeKeys: String, CodingKey {
        case value
        case range
    }

    static var zero: ValueAndRange { .init(value: 0, range: [0, 0]) }
    
    var value: AUValue
    var range: [Double]
    
    func encode(to encoder: Encoder) throws {
        
        var container = encoder.container(keyedBy: ValueRangeKeys.self)
        try container.encode(value, forKey: .value)
        try container.encode(range, forKey: .range)
    }
}

extension ValueAndRange: Decodable {
    
    init(from decoder: Decoder) throws {
        
        let container = try decoder.container(keyedBy: ValueRangeKeys.self)
        value = try container.decode(AUValue.self, forKey: .value)
        range = try container.decode([Double].self, forKey: .range)
    }
}

我不明白为什么这个结构不应该符合 Encodable。也许你们中有人比我有更好的眼睛(和大脑)?

您的编码函数错误地尝试编码类型 ValueAndRange.self,而不是值。

查看 init(from:) 方法,我认为您的编码函数应如下所示

func encode(to encoder: Encoder) throws {
    var container = encoder.container(keyedBy: EffectKeys.self)

    switch self {
    case .lowPassFilter(let effect):
        try container.encode(effect.cutOffFrequency, forKey: .cutoffFrequency)
        try container.encode(effect.resonance, forKey: .resonance)
    }
}

我没有在这段代码中包含 .effectType,因为我不确定它的用法(它不总是相同的硬编码字符串吗?)。