最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

[已解决]swift执行encodeObject去保存数据时出错unrecognized selector sent to instance

Swift crifan 4187浏览 0评论

代码:

    // 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 – Got Unrecognized selector -replacementObjectForKeyedArchiver: crash when implementing NSCoding 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)

的才可以。

相关官网文档:

Subclassing NSCoder

Archives and Serializations Programming Guide

encodeDataObject(_:) – NSCoder Class Reference

转载请注明:在路上 » [已解决]swift执行encodeObject去保存数据时出错unrecognized selector sent to instance

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
91 queries in 0.192 seconds, using 22.16MB memory