Swift报错NSInvalidArgumentException,现有解决方案无效求助
解决
-[_SwiftValue encodeWithCoder:]: unrecognized selector错误 老哥,这个错误的根源其实很明确:你试图归档的People对象里,events数组中的Event类没有正确实现NSCoding协议,而且大概率没有继承自NSObject。当Swift的非NSObject子类对象和Objective-C的归档系统交互时,会被自动包装成_SwiftValue,而这个包装类根本不支持encodeWithCoder:方法,直接触发了崩溃。
再看你给出的People类代码,不仅解码方法没写完,连编码方法都缺失了,这也会影响归档流程,但核心问题还是出在Event类上。
正确解决方案步骤:
让
Event类继承NSObject并实现NSCoding
所有要参与归档的自定义类,必须是NSObject的子类,并且实现NSCoding的两个强制方法:init(coder:)(解码逻辑)和encode(with:)(编码逻辑)。补全
People类的完整NSCoding实现
你当前的People类只写了一半解码逻辑,编码方法完全缺失,这会导致归档流程不完整。
完整代码示例:
首先是Event类的正确实现(你可以根据自己的实际属性调整):
class Event: NSObject, NSCoding { var eventName: String var eventDate: Date init(eventName: String, eventDate: Date) { self.eventName = eventName self.eventDate = eventDate super.init() // 必须调用父类初始化方法 } // 解码方法 required init(coder aDecoder: NSCoder) { eventName = aDecoder.decodeObject(forKey: "eventName") as! String eventDate = aDecoder.decodeObject(forKey: "eventDate") as! Date super.init() } // 编码方法 func encode(with aCoder: NSCoder) { aCoder.encode(eventName, forKey: "eventName") aCoder.encode(eventDate, forKey: "eventDate") } }
然后是补全后的People类:
class People: NSObject, NSCoding { var firstName : String var lastName : String var events : [Event] init(firstName: String, lastName: String) { self.firstName = firstName self.lastName = lastName self.events = [] super.init() // 别忘了调用父类初始化 } // 补全解码方法 required init(coder aDecoder: NSCoder) { firstName = aDecoder.decodeObject(forKey: "firstName") as! String lastName = aDecoder.decodeObject(forKey: "lastName") as! String events = aDecoder.decodeObject(forKey: "events") as! [Event] super.init() } // 添加编码方法 func encode(with aCoder: NSCoder) { aCoder.encode(firstName, forKey: "firstName") aCoder.encode(lastName, forKey: "lastName") aCoder.encode(events, forKey: "events") } }
关键注意事项:
- 所有要归档的属性,无论基本类型还是自定义类,都要在编码/解码方法中对应处理
- 自定义类必须继承
NSObject,因为NSCoding依赖Objective-C的运行时特性 - 解码时如果用
as!强制解包,要确保对应Key一定有值;追求安全的话可以用as?配合默认值
内容的提问来源于stack exchange,提问作者Charles B.
相关产品推荐
相关产品推荐

