I'm facing unrecognized selector sent to instance
error while using NSKeyedArchiver.archivedData
.
I was trying to store parse the JSON output to the custom class object and store it in NSUserDefaults
on successful login. I wanted to use these details in other controllers to make some other POST
calls. But while saving them in my LoginController
I'm getting this error. Can some one help in resolving this.
My Class:
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")
}
}
And on successful login, I'm storing this details.
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()
}
ERROR MESSAGE:
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
The issue might be caused because you are trying to archive an optional and Optional
doesn't have the encodeWithCoder
method (hence the error message).
Try doing this:
public func encode(with aCoder: NSCoder) {
if let token = token {
aCoder.encode(token,forKey:"token")
}
if let agentId = agentId {
aCoder.encode(agentId,forKey:"agentId")
}
}