NSKeyedArchiver保存数据失败:出现无法识别的选择器报错
解决NSKeyedArchiver保存Participant数组时的
_SwiftValue encodeWithCoder:崩溃问题 嘿,这个问题我之前也碰到过!你遇到的这个报错,本质是NSKeyedArchiver在编码你的Participant对象时,碰到了一个不支持NSCoding协议的类型,导致无法完成编码操作。下面给你一步步解决的方案:
1. 确保Participant类完全遵循NSCoding协议
NSKeyedArchiver依赖NSCoding协议来编码/解码对象,所以你的Participant类必须满足两个核心条件:
- 继承自
NSObject(因为NSCoding是Objective-C协议,Swift类需要兼容OC运行时环境) - 实现
init?(coder: NSCoder)解码方法,以及encode(with: NSCoder)编码方法,并且要覆盖所有需要持久化的属性。
举个完整的示例代码:
import Foundation class Participant: NSObject, NSCoding { // 假设你的Participant包含这些属性 var name: String var age: Int? var isActive: Bool // 自定义初始化方法 init(name: String, age: Int?, isActive: Bool) { self.name = name self.age = age self.isActive = isActive } // MARK: - NSCoding 协议实现 required init?(coder: NSCoder) { // 解码所有属性:可选类型用decodeObject,基础类型用对应decode方法 name = coder.decodeObject(forKey: "name") as! String age = coder.decodeObject(forKey: "age") as? Int isActive = coder.decodeBool(forKey: "isActive") } func encode(with coder: NSCoder) { // 编码所有属性:Swift基础类型会自动桥接OC类型,可选类型也可直接编码 coder.encode(name, forKey: "name") coder.encode(age, forKey: "age") coder.encode(isActive, forKey: "isActive") } }
2. 检查Participant的所有属性类型
如果Participant里包含自定义类型(比如枚举、其他自定义类),这些类型也必须支持NSCoding:
- 对于枚举:如果是
RawRepresentable类型(比如基于String/Int的枚举),可以编码它的rawValue,解码时再转成枚举值。示例:
enum ParticipantRole: String { case leader, member } // 在Participant的encode方法里 coder.encode(role.rawValue, forKey: "role") // 在init?(coder:)方法里 guard let roleRaw = coder.decodeObject(forKey: "role") as? String, let role = ParticipantRole(rawValue: roleRaw) else { return nil } self.role = role
- 对于其他自定义类:同样要让它继承NSObject并遵循NSCoding协议。
3. 确认数据源数组的正确性
删除UITableView行之后,确保你的数据源数组已经正确移除了对应的Participant对象,并且数组是纯粹的[Participant]类型,没有混入nil或其他不支持编码的类型。
4. 正确的保存/读取代码示例
最后,给你一个标准的保存和读取Participant数组的代码:
保存方法
func saveParticipants(_ participants: [Participant]) { // 获取Documents目录路径 guard let docsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { print("无法获取Documents目录") return } let saveURL = docsDir.appendingPathComponent("participants_archive") do { let archiveData = try NSKeyedArchiver.archivedData(withRootObject: participants, requiringSecureCoding: false) try archiveData.write(to: saveURL) print("保存成功") } catch { print("保存失败:\(error.localizedDescription)") } }
读取方法
func loadParticipants() -> [Participant]? { guard let docsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return nil } let saveURL = docsDir.appendingPathComponent("participants_archive") do { let archiveData = try Data(contentsOf: saveURL) guard let participants = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(archiveData) as? [Participant] else { return nil } return participants } catch { print("读取失败:\(error.localizedDescription)") return nil } }
按照上面的步骤检查和修改,应该就能解决这个崩溃问题啦!
内容的提问来源于stack exchange,提问作者BenjyM
相关产品推荐
相关产品推荐

