Post模型无法遵循Encodable?分页实现遇阻求指导
解决Post模型遵循Encodable的问题
直接添加Encodable协议后失败,核心原因是模型里存在几个特殊属性需要手动处理:@DocumentID属性包装器、Firebase的Timestamp类型、本地状态属性以及计算属性。以下是具体解决方案:
1. 添加Encodable协议并定义CodingKeys
先在结构体声明中加入Encodable,然后自定义CodingKeys,只保留需要编码的核心业务数据(本地状态和计算属性不需要参与分页相关的编码,直接排除):
struct Post: Identifiable, Decodable, Encodable, ScrollableData { @DocumentID var id: String? let caption: String let timestamp: Timestamp let photoUrl: String let uid: String var comments: Int var likes: Int var replyingTo: String? var edited: Bool? var user: User? var didFavourite: Bool? = false var didLike: Bool? = false var timestampString: String { let formatter = DateComponentsFormatter() formatter.allowedUnits = [.second, .minute, .hour, .day, .weekOfMonth] formatter.maximumUnitCount = 1 formatter.unitsStyle = .abbreviated return formatter.string(from: timestamp.dateValue(), to: Date()) ?? "" } var detailedTimestampString: String { let formatter = DateFormatter() formatter.dateFormat = "h:mm a · MM/dd/yyyy" return formatter.string(from: timestamp.dateValue()) } // 自定义CodingKeys,只包含需要编码的属性 enum CodingKeys: String, CodingKey { case id, caption, timestamp, photoUrl, uid, comments, likes, replyingTo, edited } }
2. 手动实现encode(to:)方法
由于@DocumentID是属性包装器,默认自动合成的编码逻辑无法正确读取它的底层值,需要手动实现编码逻辑:
func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) // 编码@DocumentID包装的id值 try container.encode(id, forKey: .id) // 编码其他核心属性 try container.encode(caption, forKey: .caption) try container.encode(timestamp, forKey: .timestamp) try container.encode(photoUrl, forKey: .photoUrl) try container.encode(uid, forKey: .uid) try container.encode(comments, forKey: .comments) try container.encode(likes, forKey: .likes) // 可选属性用encodeIfPresent避免编码nil值 try container.encodeIfPresent(replyingTo, forKey: .replyingTo) try container.encodeIfPresent(edited, forKey: .edited) }
关键注意事项
- 本地属性排除:
user、didFavourite、didLike属于本地状态(比如从缓存或其他接口加载的附加数据),不需要参与分页编码,因此在CodingKeys中排除,避免编码失败。 - Timestamp兼容性:Firebase的
Timestamp本身支持Codable,如果你的版本出现编码问题,可以手动将其转为Date后编码(替换try container.encode(timestamp, ...)为try container.encode(timestamp.dateValue(), forKey: .timestamp),同时解码逻辑也要对应调整)。 - 不破坏现有功能:自定义
CodingKeys和encode(to:)不会影响原有的Decodable功能,只要CodingKeys包含了解码所需的所有属性,自动合成的解码逻辑依然正常工作。
如果你的User模型也需要参与编码,只需让User结构体同样遵循Encodable即可(若有特殊属性,按上述方式处理)。
内容的提问来源于stack exchange,提问作者MichaelJ
相关产品推荐
相关产品推荐

