swift - 难以将带有枚举的模型与 Codable 保持一致
问题描述
写入是将模型和 EmployeeType 枚举保存/写入文件,但读取时为零。我认为错误出在 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)")
解决方案
你太难了:
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 容器基本上是一个数组。
推荐阅读
- jquery - 在 jQuery Datatable 中添加自定义下拉菜单破坏了排序操作
- azure - 在 azure 数据工厂中构建管道以加载 Excel 文件、格式化内容、转换为 csv 并发送到 azure sql DB
- php - 在另一个 php 文件中调用 php 脚本
- html - 在前台显示背景按钮
- php - W3school 中示例 PHP/AJAX 的问题
- java - 带有过滤器的 Scala 2.11 中的 Jackson 模块问题
- sql - 每组前 N 个 (MSSQL)
- java - 如何在整个 android 应用程序中使用单个 Firestore 实例?
- java - MySQLSyntaxErrorException,而我试图用java更新mysql中的日期
- python - Python - 子图仅显示底部图