如何自定义编码为 JSON 包含数组的 Swift 对象?

How do I custom encode to JSON a Swift object containing an array?

我是一名开发新手,正在编写一个 iOS 应用程序,允许用户在 'piece' 录制的音乐中定义和重放多个 'passages',每个段落多次。

My class 'Piece' 是一个 Observable 对象,目前只包含已发布的 var 'passages'(包含用户希望重放的段落详细信息的记录数组)。虽然现在 Piece 的唯一成员是一个 'passages' 数组,但我希望 Piece 最终会有更多的成员,而不是数组。

我希望能够将用户定义的每个 Piece 保存为 JSON 文件。因为 'Piece' 是一个可观察对象,它不符合 Codable 除非我编写自定义编码和解码函数。到目前为止,我一直无法找到任何示例代码来说明如何编码一个对象(在我的例子中,'Piece'),而这个对象又包含一个自定义对象数组(在我的例子中,'Passage' ) 具有多个属性。

下面显示了我的 'Piece' 和 'Passage' 代码的相关部分。

class Piece: ObservableObject, Codable {

    @Published var passages = [Passage]()
    
    enum CodingKeys: CodingKey {
        case passages
    }
  
    init() { }
    
    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
    passages = try container.decode([Passage].self, forKey: .passages)
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode([Passage](), forKey: .passages)
        
    }
}
 
struct Passage: Codable, Equatable, Identifiable, Hashable {

    var id = UUID()
    var startTime: Double
    var endTime: Double
    var extraPause: Double
    var numIterations: Int
    var skipMe: Bool = false
    
    enum PassageKeys: CodingKey {
        case id, startTime, endTime, extraPause, numIterations, skipMe
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: PassageKeys.self)
        try container.encode(id, forKey: .id)
        try container.encode(startTime, forKey: .startTime)
        try container.encode(endTime, forKey: .endTime)
        try container.encode(extraPause, forKey: .extraPause)
        try container.encode(numIterations, forKey: .numIterations)
        try container.encode(skipMe, forKey: .skipMe)
    }
}

在我的应用程序界面中,我编写了以下按钮操作。

let url = self.getDocumentsDirectory().appendingPathComponent("X.json")
let encoder = JSONEncoder()
do {
    let data = try encoder.encode(self.piece)
        let string = String(data: data, encoding: .utf8)!
        print("Here is the string we are trying to write: \(string)")
        try string.write(to: url, atomically: true, encoding: .utf8)
   } catch {
        print(error.localizedDescription)
}

当我用几条记录填充 'passages' 数组然后单击触发此操作的按钮时,控制台输出为:

Here is the string we are trying to write: {"passages":[]}

在 Passage.encode() 函数内设置断点表明此函数从未被调用。

谁能帮我指明正确的方向?

你应该改变

try container.encode([Passage](), forKey: .passages)

try container.encode(passages, forKey: .passages)

在你的代码中。否则你总是试图编码新的空数组 [Passage]().