首页 > 解决方案 > 如何使用枚举和关联的自定义对象读取和写入对象?

问题描述

我正试图围绕如何为 Firestore 创建一个可编码对象,该对象可以在其中保存一组自定义对象类型。我已经设法为我想要存储的每种对象类型创建了一个带有枚举的可编码对象,但是我正在努力如何读取或写入它,我开始怀疑我错了完全路径。

下面是我正在尝试做的一个例子。

struct myView:View {
    @Binding var entry:JournalEntry
    
    var body: some View {
        VStack {
            Text("Title: \(entry.title)")
            Text("Content: \(/* WHAT TO PUT HERE? */)")
            TextField("RecordA text", text: /* WHAT TO PUT HERE? */)
        }
    }
}

struct Journal:Codable, Identifiable {
   var id = UUID().uuidString
   var entries:[JournalEntry]
}

struct JournalEntry:Codable, Identifiable {
    var id:String
    var title: String
    var date:Date
    var entryContent:EntryType
}

struct RecordA: Codable {
    var text:String = ""
    var image:String = ""
}

struct RecordB: Codable {
    var laps:Int = 0
    var jumps:Int = 0
}

enum EntryType: Codable {
    case recordTypeA(RecordA)
    case recordTypeB(RecordB)
}

extension EntryType {

private enum CodingKeys: String, CodingKey {
    case base, recordTypeAObject, recordTypeBObject
}

private enum Base: String, Codable {
    case recordTypeA, recordTypeB
}

func encode(to encoder: Encoder) throws {
    var container = encoder.container(keyedBy: CodingKeys.self)
    switch self {
    case .recordTypeA:
        try container.encode(RecordA(), forKey: .recordTypeAObject)
    case .recordTypeB:
        try container.encode(RecordB(), forKey: .recordTypeBObject)
    }
}

init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    let base = try container.decode(Base.self, forKey: .base)
    switch base {
    case .recordTypeA:
        if let content = try? decoder.singleValueContainer().decode(RecordA.self) {
            self = .recordTypeA(content)
            return
        }
    case .recordTypeB:
        if let content = try? decoder.singleValueContainer().decode(RecordB.self) {
            self = . recordTypeB(content)
            return
        }
    }
    
    throw ContentError.missingValue
}

enum ContentError:Error {
    case missingValue
}
    
}

标签: swiftenumsswiftui

解决方案


为了查看内容,我将为每个结构创建一个视图

struct RecordAView: View {
    var record: RecordA
    var body: some View {
        VStack {
            Image(record.image)
            Text(record.text)
        }
    }
}

struct RecordBView: View {
    var record: RecordB
    var body: some View {
        HStack {
            Text("\(record.jumps)")
            Text("\(record.laps)")
        }
    }
}

然后修改myView以显示正确的数据

struct myView:View {
    @Binding var entry:JournalEntry

    var body: some View {
        VStack {
            Text("Title: \(entry.title)")
            viewForContent(entry.entryContent)
        }
    }

    func viewForContent(_ content: EntryType) -> some View {
        switch content {
            case .recordTypeA(let record):
                return AnyView(RecordAView(record: record))
            case .recordTypeB(let record):
                return AnyView(RecordBView(record: record))
            }
        }
    }
}

推荐阅读