SwiftUI添加自定义Decoder后Absence结构体实例化参数错误求助
问题原因
你遇到的"extra arguments at positions"错误,核心原因是:当你为结构体自定义了init(from: Decoder)解码初始化器后,Swift会自动移除默认生成的成员逐一初始化器。原来的Absence(id: 1, userId: 1, ...)调用方式依赖默认初始化器,现在它不存在了,因此触发参数错误。
解决方案
以下两种方式都能解决问题,可根据代码习惯选择:
方案一:手动添加成员逐一初始化器
在结构体中显式声明与属性匹配的初始化器,同时保留自定义解码逻辑:
struct Absence: Codable, Identifiable, Hashable { var id: Int var userId: Int var start: Date var end: Date var active: Bool var modifiedBy: Int var modified: Date // 手动添加成员逐一初始化器 init(id: Int, userId: Int, start: Date, end: Date, active: Bool, modifiedBy: Int, modified: Date) { self.id = id self.userId = userId self.start = start self.end = end self.active = active self.modifiedBy = modifiedBy self.modified = modified } // 自定义解码初始化器 init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) id = try container.decode(Int.self, forKey: .id) userId = try container.decode(Int.self, forKey: .userId) active = try container.decode(Bool.self, forKey: .active) modifiedBy = try container.decode(Int.self, forKey: .modifiedBy) let dateFormatter = DateFormatter() dateFormatter.dateFormat = "MM/dd/yyyy" if let startDateString = try? container.decode(String.self, forKey: .start), let startDate = dateFormatter.date(from: startDateString) { start = startDate } else { start = Date() } if let endDateString = try? container.decode(String.self, forKey: .end), let endDate = dateFormatter.date(from: endDateString) { end = endDate } else { end = Date() } if let modifiedString = try? container.decode(String.self, forKey: .modified), let modifiedDate = dateFormatter.date(from: modifiedString) { modified = modifiedDate } else { modified = Date() } } static func sampleData() -> Absence { let dateFormatter = DateFormatter() dateFormatter.dateFormat = "MM/dd/yyyy" let startString = "01/01/2021" let endString = "01/02/2021" let modifiedString = "01/03/2021" let startDate = dateFormatter.date(from: startString) ?? Date() let endDate = dateFormatter.date(from: endString) ?? Date() let modifiedDate = dateFormatter.date(from: modifiedString) ?? Date() return Absence(id: 1, userId: 1, start: startDate, end: endDate, active: true, modifiedBy: 1, modified: modifiedDate) } }
方案二:将解码逻辑放到扩展中
把init(from:)移到结构体扩展里,这样结构体仍会保留默认的成员逐一初始化器,无需手动添加:
struct Absence: Codable, Identifiable, Hashable { var id: Int var userId: Int var start: Date var end: Date var active: Bool var modifiedBy: Int var modified: Date static func sampleData() -> Absence { let dateFormatter = DateFormatter() dateFormatter.dateFormat = "MM/dd/yyyy" let startString = "01/01/2021" let endString = "01/02/2021" let modifiedString = "01/03/2021" let startDate = dateFormatter.date(from: startString) ?? Date() let endDate = dateFormatter.date(from: endString) ?? Date() let modifiedDate = dateFormatter.date(from: modifiedString) ?? Date() return Absence(id: 1, userId: 1, start: startDate, end: endDate, active: true, modifiedBy: 1, modified: modifiedDate) } } // 扩展中实现自定义解码逻辑 extension Absence { init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) id = try container.decode(Int.self, forKey: .id) userId = try container.decode(Int.self, forKey: .userId) active = try container.decode(Bool.self, forKey: .active) modifiedBy = try container.decode(Int.self, forKey: .modifiedBy) let dateFormatter = DateFormatter() dateFormatter.dateFormat = "MM/dd/yyyy" if let startDateString = try? container.decode(String.self, forKey: .start), let startDate = dateFormatter.date(from: startDateString) { start = startDate } else { start = Date() } if let endDateString = try? container.decode(String.self, forKey: .end), let endDate = dateFormatter.date(from: endDateString) { end = endDate } else { end = Date() } if let modifiedString = try? container.decode(String.self, forKey: .modified), let modifiedDate = dateFormatter.date(from: modifiedString) { modified = modifiedDate } else { modified = Date() } } // 扩展实现解码需显式声明CodingKeys enum CodingKeys: String, CodingKey { case id, userId, start, end, active, modifiedBy, modified } }
补充说明
- 方案一逻辑直接,适合大多数场景;方案二通过扩展分离解码逻辑,保持结构体主体简洁,但需显式定义
CodingKeys。 - 两种方案都能恢复
Absence(id: ...)的实例化方式,解决参数错误问题。
内容的提问来源于stack exchange,提问作者cristian9804
相关产品推荐
相关产品推荐

