【问题标题】:Having trouble with conforming model with enums to Codable难以将带有枚举的模型与 Codable 保持一致
【发布时间】:2020-02-03 13:40:28
【问题描述】:

Write 是将模型和 EmployeeType 枚举保存/写入文件,但在读取时变为 nil。我认为错误出在 EmployeeType 枚举的解码扩展中?我添加了打印 URL 以验证写入和读取目录和文件是否相同。第三个打印显示来自读取/解码方法 readEmployeesFromFile() 的返回“decodedEmployees”返回 nil,这意味着错误在“let decodedEmployees = try?...”中

import UIKit
struct Employee: Codable {

    var name: String
    var dateOfBirth: Date
    var employeeType: EmployeeType
}

enum EmployeeType: Codable {
    case exempt
    case nonExempt
    case partTime

    static let all: [EmployeeType] = [.exempt, .nonExempt, .partTime]

    func description() -> String {
        switch self {
        case .exempt:
            return "Exempt Full Time"
        case .nonExempt:
            return "Non-exempt Full Time"
        case .partTime:
            return "Part Time"
        }
    }
}

extension EmployeeType {
    init(from decoder: Decoder) throws {
        var container = try decoder.unkeyedContainer()
        let employeeType = try container.decode(EmployeeType.self)
        self = employeeType

        return
        }
     func encode(to encoder: Encoder) throws {
        var container = encoder.unkeyedContainer()
        try container.encode(description())
        return
    }
}

var count = 0
 func readEmployeeFromFile()->[Employee] {
       let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
       let archiveURL = documentsDirectory.appendingPathComponent("Employees").appendingPathExtension("plist")
       let employeeDecoder = PropertyListDecoder()
            print("Read: \(archiveURL)")
    if let employeesDataFromFile = try? Data(contentsOf: archiveURL) {
        let decodedEmployees = try? employeeDecoder.decode(Array<Employee>.self, from: employeesDataFromFile)
        print("failed read if nil: \(decodedEmployees)")
    }
    return[Employee(name: "Fail", dateOfBirth: Date(), employeeType: .partTime)]
}

    func writeEmployeeToFile(newEmployeesToSave: [Employee]){
        let documentsDirectory =
            FileManager.default.urls(for: .documentDirectory,
                in: .userDomainMask).first!
            let archiveURL =
            documentsDirectory.appendingPathComponent("Employees")
               .appendingPathExtension("plist")
            print("Write: \(archiveURL)")
        let propertyListEncoder = PropertyListEncoder()
        let savedEmployees = try? propertyListEncoder.encode(newEmployeesToSave)
        try? savedEmployees!.write(to: archiveURL, options: .noFileProtection)
    }

let emps = [Employee(name: "A", dateOfBirth: Date(), employeeType: .exempt)]
writeEmployeeToFile(newEmployeesToSave: emps)
let readEmps = readEmployeeFromFile()
print("read: \(readEmps)")

【问题讨论】:

    标签: swift enums codable


    【解决方案1】:

    你太难了:

    enum EmployeeType: String, Codable, CaseIterable {
      case exempt = "Exempt Full Time"
      case nonExempt = "Non-exempt Full Time"
      case partTime = "Part Time"
    }
    

    其他一切都会起作用。 allCases 属性是自动生成的。

    如果您真的想自己进行编码,您应该查看singleValueContainer 而不是unkeyedContainer 并使用init(rawValue:) 进行初始化。 Unkeyed 容器基本上是一个数组。

    【讨论】:

    • 扩展这个答案,我会将枚举嵌套在Employee 结构上并将其重命名为Kind。类似于struct Employee: Codable { let name: String let dateOfBirth: Date let kind: Kind enum Kind: String, Codable, CaseIterable { case exempt = "Exempt Full Time", nonExempt = "Non-exempt Full Time", partTime = "Part Time" } } 和声明let employeeKind: Employee.Kind = .exempt
    • 谢谢 - 工作!不知道 caseiterable 协议。并且“kind”枚举更清晰。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-16
    • 2012-09-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多