Swift Codable 结构递归地将自身包含为属性

Cry*_*thm 1 recursion swift codable

我有一个相当大的结构,符合Codable,并且它的属性之一需要与其本身具有相同的类型。我正在尝试做的事情的简短示例如下所示:

struct Message: Codable {
    let content: String
    // ...other values
    let reference: Message // <-- Error: Value type 'Message' cannot have a stored property that recursively contains it
}
Run Code Online (Sandbox Code Playgroud)

Swift 似乎不允许结构体递归地将自身包含为其值之一。Message除了创建一个完整的重复结构(这会将其变成先有鸡还是先有蛋的问题,其中重复结构不能包含自身等)之外,还有什么方法可以使其工作吗?不创建重复的结构还允许我重用接收和呈现Message结构的 SwiftUI 代码。

Swe*_*per 5

一个简单的方法是将结构体更改为类:

class Message: Codable {
    let content: String
    // ...other values
    let reference: Message? // optional - the recursion has to end somewhere right?
}
Run Code Online (Sandbox Code Playgroud)

但这可能会破坏代码的其他部分,因为结构和类具有截然不同的语义。

另一种方法是创建引用类型Box

class Box<T: Codable>: Codable {
    let wrappedValue: T
    required init(from decoder: Decoder) throws {
        wrappedValue = try T(from: decoder)
    }
    
    func encode(to encoder: Encoder) throws {
        try wrappedValue.encode(to: encoder)
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,

struct Message: Codable {
    let content: String
    // ...other values
    
    let boxedReference: Box<Message>?
    
    // you can still refer to 'reference' as 'reference' in your swift code
    var reference: Message? { boxedReference?.wrappedValue }
    
    enum CodingKeys: String, CodingKey {
        case content, boxedReference = "reference"
    }
}
Run Code Online (Sandbox Code Playgroud)