代码:
// MARK: – State Restoring private let encodeKeyTeamItemList = "encodeKeyTeamItemList" private let encodeKeyCurTeamItemIdx = "encodeKeyCurTeamItemIdx" override func encodeRestorableStateWithCoder(coder: NSCoder) { super.encodeRestorableStateWithCoder(coder) coder.encodeObject(gTeamTableViewData, forKey: "gTeamTableViewData") coder.encodeObject(gTeamTableViewData.teamItemList, forKey: encodeKeyTeamItemList) coder.encodeInteger(gTeamTableViewData.curTeamItemIdx, forKey: encodeKeyCurTeamItemIdx) } |
执行时,对应的:
coder.encodeObject(gTeamTableViewData, forKey: "gTeamTableViewData") |
出错:
2016-01-09 11:04:03.871 JianDao[2482:93931] -[JianDao.TeamTableViewData encodeWithCoder:]: unrecognized selector sent to instance 0x79e23030 2016-01-09 11:04:03.875 JianDao[2482:93931] *** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘-[JianDao.TeamTableViewData encodeWithCoder:]: unrecognized selector sent to instance 0x79e23030’ *** First throw call stack: ( 0 CoreFoundation 0x013bfa14 __exceptionPreprocess + 180 1 libobjc.A.dylib 0x036b0e02 objc_exception_throw + 50 2 CoreFoundation 0x013c8d63 -[NSObject(NSObject) doesNotRecognizeSelector:] + 275 3 CoreFoundation 0x013066bd ___forwarding___ + 1037 4 CoreFoundation 0x0130628e _CF_forwarding_prep_0 + 14 5 Foundation 0x019a4301 _encodeObject + 1304 6 Foundation 0x019a3de1 -[NSKeyedArchiver encodeObject:forKey:] + 209 7 JianDao 0x001dbe3f _TFC7JianDao19SwitchTeamTableView30encodeRestorableStateWithCoderfS0_FCSo7NSCoderT_ + 271 8 JianDao 0x001dc12d _TToFC7JianDao19SwitchTeamTableView30encodeRestorableStateWithCoderfS0_FCSo7NSCoderT_ + 61 9 UIKit 0x0220f377 _encodeRestorationStateForViewAndSubviews + 437 10 UIKit 0x0221b52d ___encodeRestorationStateForViewAndSubviews_block_invoke + 26 11 CoreFoundation 0x012dc273 __53-[__NSArrayM enumerateObjectsWithOptions:usingBlock:]_block_invoke + 99 12 CoreFoundation 0x012db9a2 -[__NSArrayM enumerateObjectsWithOptions:usingBlock:] + 226 13 CoreFoundation 0x012db835 -[NSArray enumerateObjectsUsingBlock:] + 53 14 UIKit 0x0220f439 _encodeRestorationStateForViewAndSubviews + 631 15 UIKit 0x0220e72a -[UIApplication(StateRestoration) _saveApplicationPreservationState:viewController:sessionIdentifier:beginHandler:completionHandler:] + 5631 16 UIKit 0x0220cb86 -[UIApplication(StateRestoration) _saveApplicationPreservationStateIfSupported] + 640 17 UIKit 0x021e92d0 -[UIApplication _applicationDidEnterBackground] + 121 18 UIKit 0x021e98d2 -[UIApplication _handleApplicationDeactivationWithScene:shouldForceExit:transitionContext:completion:] + 934 19 UIKit 0x02202c81 __88-[UIApplication _handleApplicationLifecycleEventWithScene:transitionContext:completion:]_block_invoke + 150 20 UIKit 0x02202b83 -[UIApplication _handleApplicationLifecycleEventWithScene:transitionContext:completion:] + 469 21 UIKit 0x021dde43 __70-[UIApplication scene:didUpdateWithDiff:transitionContext:completion:]_block_invoke + 197 22 UIKit 0x021dda33 -[UIApplication scene:didUpdateWithDiff:transitionContext:completion:] + 770 23 FrontBoardServices 0x05f38d23 __80-[FBSSceneImpl updater:didUpdateSettings:withDiff:transitionContext:completion:]_block_invoke_2 + 71 24 FrontBoardServices 0x05f3865a __40-[FBSSceneImpl _performDelegateCallOut:]_block_invoke + 54 25 FrontBoardServices 0x05f5c173 -[FBSSerialQueue _performNext] + 184 26 FrontBoardServices 0x05f5c5aa -[FBSSerialQueue _performNextFromRunLoopSource] + 52 27 FrontBoardServices 0x05f5b8a6 FBSSerialQueueRunLoopSourceHandler + 33 28 CoreFoundation 0x012d96ff __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15 29 CoreFoundation 0x012cf38b __CFRunLoopDoSources0 + 523 30 CoreFoundation 0x012ce7a8 __CFRunLoopRun + 1032 31 CoreFoundation 0x012ce0e6 CFRunLoopRunSpecific + 470 32 CoreFoundation 0x012cdefb CFRunLoopRunInMode + 123 33 GraphicsServices 0x05057664 GSEventRunModal + 192 34 GraphicsServices 0x050574a1 GSEventRun + 104 35 UIKit 0x021e0bfa UIApplicationMain + 160 36 JianDao 0x000edd1c main + 140 37 libdyld.dylib 0x04402a21 start + 1 ) libc++abi.dylib: terminating with uncaught exception of type NSException |
其中可以看到:
(lldb) po gTeamTableViewData <JianDao.TeamTableViewData: 0x79e23030> |
说白了:就是encode的数据类型不支持。
但是要搞明白,如何解决。
搜:
encodeObject unrecognized selector sent to instance
ios – encodeWithCoder: unrecognized selector sent to instance – Stack Overflow
ios – Unrecognized selector sent to instance while archiving data (NSCoding) – Stack Overflow
encodeWithCoder: unrecognized selector sent to instance [duplicate]-BaseDB基础信息网
数据持久化(三)使用NSKeyedArchiver归档 – Jymn_Chen – 博客频道 – CSDN.NET
How to implement NSCoding on a generic class in Swift? [如何实现快速nscoding对泛型类?] – 问题-字节技术
swift encodeObject unrecognized selector sent to instance
How to implement NSCoding on a generic class in Swift? – Stack Overflow
ios – Encode Object in Swift – Stack Overflow
ios – Why is there an uncaught exception? – Stack Overflow
后来,把相关的类,类中的数组的元素对应的类,都去实现了coding相关的支持:
class SwitchTeamTableView: UIView{ var allowSwitch:Bool = true var tableView:UITableView = UITableView() var switchTeamFrame:CGRect = CGRectZero override init(frame:CGRect) { 。。。 super.init(frame:switchTeamFrame) 。。。 comminInit() 。。。 self.restorationIdentifier = String(self.dynamicType) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } func comminInit(){ tableView.delegate = gTeamTableViewData tableView.dataSource = gTeamTableViewData } // MARK: – State Restoring private let encodeKey_gTeamTableViewData = "SwitchTeamTableView_gTeamTableViewData" override func encodeRestorableStateWithCoder(coder: NSCoder) { super.encodeRestorableStateWithCoder(coder) coder.encodeObject(gTeamTableViewData, forKey: encodeKey_gTeamTableViewData) } override func decodeRestorableStateWithCoder(coder: NSCoder) { super.decodeRestorableStateWithCoder(coder) if let teamTableViewData = coder.decodeObjectForKey(encodeKey_gTeamTableViewData) as? TeamTableViewData { gTeamTableViewData = teamTableViewData } } } |
var gTeamTableViewData:TeamTableViewData! class TeamTableViewData: NSObject, NSCoding, UITableViewDataSource, UITableViewDelegate{ var teamItemList:[TeamItem] var curTeamItemIdx:Int override init() { teamItemList = [TeamItem]() // curTeamItemIdx = 0 curTeamItemIdx = –1 super.init() } // MARK: NSCoding private let codingKey_teamItemList = "TeamTableViewData_teamItemList" private let codingKey_curTeamItemIdx = "TeamTableViewData_curTeamItemIdx" required init?(coder aDecoder: NSCoder){ self.teamItemList = aDecoder.decodeObjectForKey(codingKey_teamItemList) as! [TeamItem] self.curTeamItemIdx = aDecoder.decodeIntegerForKey(codingKey_curTeamItemIdx) super.init() } func encodeWithCoder(aCoder: NSCoder){ aCoder.encodeObject(teamItemList, forKey: codingKey_teamItemList) aCoder.encodeInteger(curTeamItemIdx, forKey: codingKey_curTeamItemIdx) } |
class TeamItem:NSObject, NSCoding { var id:String = "" var name:String = "" var groupTopicIdList:[String] var memberIdList:[String] // var adminIdList:[String] // var timestamp:NSDate // var ownerId:String override init(){ self.id = "" self.name = "" self.groupTopicIdList = [String]() self.memberIdList = [String]() super.init() } // MARK: NSCoding private let codingKey_id = "TeamItem_id" private let codingKey_name = "TeamItem_name" private let codingKey_groupTopicIdList = "TeamItem_groupTopicIdList" private let codingKey_memberIdList = "TeamItem_memberIdList" required init?(coder aDecoder: NSCoder){ self.id = aDecoder.decodeObjectForKey(codingKey_id) as! String self.name = aDecoder.decodeObjectForKey(codingKey_name) as! String self.groupTopicIdList = aDecoder.decodeObjectForKey(codingKey_groupTopicIdList) as! [String] self.memberIdList = aDecoder.decodeObjectForKey(codingKey_memberIdList) as! [String] super.init() } func encodeWithCoder(aCoder: NSCoder){ aCoder.encodeObject(id, forKey: codingKey_id) aCoder.encodeObject(name, forKey: codingKey_name) aCoder.encodeObject(groupTopicIdList, forKey: codingKey_groupTopicIdList) aCoder.encodeObject(memberIdList, forKey: codingKey_memberIdList) } } |
就可以了。
[总结]
如果想要去调用:encodeObject的话,则必须要是,被encode的对象本身,是支持NSCoding的
-》对应的类,是支持NSCoding的,且其内部的变量也都正确的编码了:
注:想要NSCoding正常工作,则必须同时也继承NSObject
class SomeClass:NSObject, NSCoding { var val1:String var val2:[String] override init(){ self.val1 = "" self.val2 = [String]() super.init() } // MARK: NSCoding private let codingKey_val1 = "SomeClass_val1" private let codingKey_val2 = "SomeClass_val2" required init?(coder aDecoder: NSCoder){ self.val1 = aDecoder.decodeObjectForKey(codingKey_val1) as! String self.val2 = aDecoder.decodeObjectForKey(codingKey_val2) as! [String] super.init() } func encodeWithCoder(aCoder: NSCoder){ aCoder.encodeObject(val1, forKey: codingKey_val1) aCoder.encodeObject(val2, forKey: codingKey_val2) } } |
才可以。
并且,如果该类中的自己的变量,又是对应的某个类(的数组)的话,则该类也是需要支持NSCoding 的-》也是类似上面,支持NSCoding且实现了
init?(coder aDecoder: NSCoder)
和:
encodeWithCoder(aCoder: NSCoder)
的才可以。
相关官网文档:
Archives and Serializations Programming Guide
encodeDataObject(_:) – NSCoder Class Reference
转载请注明:在路上 » [已解决]swift执行encodeObject去保存数据时出错unrecognized selector sent to instance