2016-12-05 111 views
0

我在使用NSKeyedArchiver.archivedData時遇到了unrecognized selector sent to instance錯誤。NSKeyedArchiver - 發送到實例錯誤的無法識別的選擇器

我正在嘗試將JSON輸出解析爲自定義類對象,並在成功登錄時將其存儲在NSUserDefaults中。我想在其他控制器中使用這些細節來調用其他一些POST。但在將它們保存在我的LoginController中時,出現此錯誤。有人能幫助解決這個問題嗎?

我的班級:

class UserDetails : NSObject,NSCoding { 


    var token:String? 
    var agentId: Int? 
    var userId:Int? 


    //to directly get values from JSON output 

    init?(user: [String: Any]) { 

     guard let token = user["token"] as? String, 
      let agentId = user["agent_id"] as? Int, 
      let userId = user["user_id"] as? Int 
     else{ 
      return nil 
     } 


       self.token = token; 
       self.agentId = agentId; 
       self.userId = userId; 
     } 

    init(pToken:String,pAgentId:Int,pUserId:Int) 
    { 
     token = pToken; 
     agentId = pAgentId; 
     userId = pUserId; 
    } 

    //TO SAVE IN NSUSERDEFAULTS 

    required init?(coder aDecoder: NSCoder){ 
     self.token = aDecoder.decodeObject(forKey: "token") as? String 
     self.agentId = aDecoder.decodeObject(forKey: "agentId") as? Int 
     self.userId = aDecoder.decodeObject(forKey: "userId") as? Int 

     return self 
    } 

    public func encode(with aCoder: NSCoder) { 
     aCoder.encode(token,forKey:"token") 
     aCoder.encode(agentId,forKey:"agentId") 
    } 

} 

而且在成功登錄,我存儲這個細節。

LoginViewController:

if let userDict = json["user"] as? [String:Any] 
         { 
          guard let userObject = UserDetails(user:userDict) else { 
           print("Failed to create user from dictionary") 
           return 
          } 
          DispatchQueue.main.async { 

           self.saveUserItemToDefault(userObject: userObject); 

           self.dismiss(animated: true, completion: nil) 
           self.performSegue(withIdentifier: "loginSuccessIdentifier", sender: userObject) 

          } 
         } 




func saveUserItemToDefault(userObject:UserDetails) -> Void { 
      let encodedToken = NSKeyedArchiver.archivedData(withRootObject: userObject.token) //error is thrown on the first archiver call 
      let encodedAgentId = NSKeyedArchiver.archivedData(withRootObject: userObject.agentId) 
      let encodedUserId = NSKeyedArchiver.archivedData(withRootObject: userObject.userId) 

let encodedArray:[NSData] = [encodedToken as NSData,encodedAgentId as NSData,encodedUserId as NSData] 

      self.prefs.set(encodedArray, forKey: "UserDetailsItem") 
      self.prefs.synchronize() 
     } 

錯誤消息:

2016-12-05 18:08:57.917 ABCAPP[2800:183556] -[_SwiftValue encodeWithCoder:]: unrecognized selector sent to instance 0x600000079f00 
2016-12-05 18:08:57.920 ABCAPP[2800:183556] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_SwiftValue encodeWithCoder:]: unrecognized selector sent to instance 0x600000079f00' 
*** First throw call stack: 
(
    0 CoreFoundation      0x0000000104b5e34b __exceptionPreprocess + 171 
    1 libobjc.A.dylib      0x00000001045bf21e objc_exception_throw + 48 
    2 CoreFoundation      0x0000000104bcdf34 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132 
    3 CoreFoundation      0x0000000104ae3c15 ___forwarding___ + 1013 
    4 CoreFoundation      0x0000000104ae3798 _CF_forwarding_prep_0 + 120 
    5 Foundation       0x00000001040f855c _encodeObject + 1263 
    6 Foundation       0x000000010412d29a +[NSKeyedArchiver archivedDataWithRootObject:] + 156 
    7 ABCAPP      0x0000000103fa8d4b _TFC15ABCAPP19LoginViewController21saveUserItemToDefaultfT10userObjectCS_11UserDetails_T_ + 235 
    8 ABCAPP      0x0000000103face3d _TFFFC15ABCAPP19LoginViewController10checkLoginFPs9AnyObject_T_U_FTGSqV10Foundation4Data_GSqCSo11URLResponse_GSqPs5Error___T_U_FT_T_ + 77 
    9 ABCAPP      0x0000000103f9d627 _TTRXFo___XFdCb___ + 39 
    10 libdispatch.dylib     0x0000000108112980 _dispatch_call_block_and_release + 12 
    11 libdispatch.dylib     0x000000010813c0cd _dispatch_client_callout + 8 
    12 libdispatch.dylib     0x000000010811c8d6 _dispatch_main_queue_callback_4CF + 406 
    13 CoreFoundation      0x0000000104b224f9 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9 
    14 CoreFoundation      0x0000000104ae7f8d __CFRunLoopRun + 2205 
    15 CoreFoundation      0x0000000104ae7494 CFRunLoopRunSpecific + 420 
    16 GraphicsServices     0x000000010910da6f GSEventRunModal + 161 
    17 UIKit        0x0000000104f81f34 UIApplicationMain + 159 
    18 ABCAPP      0x0000000103faff2f main + 111 
    19 libdyld.dylib      0x000000010818868d start + 1 
    20 ???         0x0000000000000001 0x0 + 1 
) 
libc++abi.dylib: terminating with uncaught exception of type NSException 
+1

什麼是整個錯誤消息?這可能有助於準確找到問題所在,而不是讀取所有代碼。 – Larme

+0

@Larme添加了錯誤消息。請看一看。 – ASN

回答

1

隨着來自JPetricValentin Radu的輸入,我修改了一些代碼,並刪除了錯誤。

下面是我的解決辦法:

class UserDetails : NSObject,NSCoding { 

     //var token:String? 
     var token:String! 

     //var agentId: Int? 
     var agentId: Int! 

     //var userId:Int? 
     var userId:Int! 


    //to directly get values from JSON output 

    init?(user: [String: Any]) { 

     guard let token = user["token"] as? String, 
      let agentId = user["agent_id"] as? Int, 
      let userId = user["user_id"] as? Int 
     else{ 
      return nil 
     } 


       self.token = token; 
       self.agentId = agentId; 
       self.userId = userId; 
     } 

    init(pToken:String,pAgentId:Int,pUserId:Int) 
    { 
     token = pToken; 
     agentId = pAgentId; 
     userId = pUserId; 
    } 

    //TO SAVE IN NSUSERDEFAULTS 

    required init?(coder aDecoder: NSCoder){ 
     self.token = aDecoder.decodeObject(forKey: "token") as? String 
     self.agentId = aDecoder.decodeObject(forKey: "agentId") as? Int 
     self.userId = aDecoder.decodeObject(forKey: "userId") as? Int 

     return self 
    } 

    public func encode(with aCoder: NSCoder) { 
     aCoder.encode(token,forKey:"token") 
     aCoder.encode(agentId,forKey:"agentId") 
    } 

} 
3

因爲你試圖存檔一個可選的Optional沒有encodeWithCoder方法的問題可能造成的(因此錯誤信息)。

試着這樣做:

public func encode(with aCoder: NSCoder) { 
     if let token = token { 
      aCoder.encode(token,forKey:"token") 
     } 
     if let agentId = agentId { 
      aCoder.encode(agentId,forKey:"agentId") 
     } 
    } 
+0

嗨JPetric。我嘗試將代碼更改爲上面提到的內容。同樣的錯誤。 – ASN

+0

只是爲了我的curtesy,你能嘗試在類聲明(var token:String而不是var token:String?)中聲明token和agentId爲String和Int(不是可選項)嗎? – JPetric

+0

我試着將它改爲你的建議(不是可選項)。現在它拋出了一個類似這樣的錯誤:'如果讓令牌=令牌{aCoder.encode(令牌,forKey:「令牌」}},條件綁定的初始化程序必須具有可選類型,而不是附近的字符串}' – ASN

1

除了什麼@JPetric已經說了,可能我真的,當你得到這樣的異常,在一般情況下,問題是,你試圖存檔數據在Objective-C中不能表示的類型。這可以是一個可選的,快速的枚舉,快速的閉包等。添加一個異常斷點來查看未能編碼的實際對象,然後找到一種使用Objective-C對象的方法。

+0

我同意。添加一個異常斷點是必須的(http://stackoverflow.com/questions/17802662/exception-breakpoint-in-xcode) – JPetric

相關問題