但是,收到一条错误消息,指出我的类'Expenses‘不符合协议'Decodable’&类型'Expenses‘不符合协议'Encodable’。
import Foundation
class Expenses : ObservableObject, Codable {
@Published var items : [ExpenseItem] {
// Step 1 creat did set on publsihed var.
didSet {
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(items) {
UserDefaults.standard.set(encoded, forKey: "Items")
}
}
}
init() {
if let items = UserDefaults.standard.data(forKey: "Items") {
let decoder = JSONDecoder(
if let decoded = try?
decoder.decode([ExpenseItem].self, from: items) {
self.items = decoded
return
}
}
self.items = []
}
}
我的费用项被标记为
struct ExpenseItem : Identifiable, Codable {
let id = UUID()
let name : String
let type : String
let amount : Int
}
发布于 2020-09-15 20:52:49
当所有存储的属性都符合Encodable
/Decodable
时,符合Encodable
/Decodable
是自动合成的,但是在属性上使用属性包装器意味着现在属性包装器类型需要符合Encodable
/Decodable
。
@Published
属性包装不符合。如果只在Published
类型本身上实现一致性就好了,但不幸的是它没有公开包装值,所以如果不使用反射(我在网上看到了一些建议),我认为这是不可能的。
您需要手动实现一致性:
class Expenses : ObservableObject {
@Published var items : [ExpenseItem]
// ... rest of your code
}
extension Expense: Codable {
enum CodingKeys: CodingKey {
case items
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.items, forKey: .items)
}
required init(from decoder: Decoder) throws {
var container = try decoder.container(keyedBy: CodingKeys.self)
self.items = try container.decode([ExpenseItem].self, forKey: .items)
}
}
https://stackoverflow.com/questions/63908507
复制