Hi,
I'm trying to create a new target duplicated from the main target (cdx_ios
) called cdx-ios-dev02
. I also made a new scheme called cdx-ios-dev02
It can be built just fine however when I run it, it crashed and it throws this exception:
*** Terminating app due to uncaught exception 'NSInvalidUnarchiveOperationException', reason: '*** -[NSKeyedUnarchiver decodeObjectForKey:]: cannot decode object of class (cdx_ios.AuthObject) for key (root) because no class named "cdx_ios.AuthObject" was found; the class needs to be defined in source code or linked in from a library (ensure the class is part of the correct target). If the class was renamed, use setClassName:forClass: to add a class translation mapping to NSKeyedUnarchiver'
This is the class:
class AuthObject: NSObject, NSCoding {
var accessT1: String = ""
var t1Type: String = "bearer"
var refreshT1: String = ""
var expiresIn: Int = 0
var scope: String = ""
var jti: String = ""
init(accessT1: String = "",
t1Type: String = "bearer",
refreshT1: String = "",
expiresIn: Int = 0,
scope: String = "",
jti: String = "") {
self.accessT1 = accessT1
self.t1Type = t1Type
self.refreshT1 = refreshT1
self.expiresIn = expiresIn
self.scope = scope
self.jti = jti
}
convenience init(dic: [String: Any]) {
self.init()
mapping(dic)
}
required convenience init(coder aDecoder: NSCoder) {
let t1 = aDecoder.decodeObject(forKey: "accessT1") as? String ?? ""
let t1Type = aDecoder.decodeObject(forKey: "t1Type") as? String ?? ""
let refreshT1 = aDecoder.decodeObject(forKey: "refreshT1") as? String ?? ""
let expiresIn = aDecoder.decodeInteger(forKey: "expiresIn")
let scope = aDecoder.decodeObject(forKey: "scope") as? String ?? ""
let jti = aDecoder.decodeObject(forKey: "jti") as? String ?? ""
self.init(
accessT1: t1,
t1Type: t1Type,
refreshT1: refreshT1,
expiresIn: expiresIn,
scope: scope,
jti: jti
)
}
func mapping(_ dic: [String: Any]) {
accessT1 = ParseUtil.dictionaryValue(dic, "access_token", "")
t1Type = ParseUtil.dictionaryValue(dic, "token_type", "bearer")
refreshT1 = ParseUtil.dictionaryValue(dic, "refresh_token", "")
expiresIn = ParseUtil.dictionaryValue(dic, "expires_in", 0)
scope = ParseUtil.dictionaryValue(dic, "scope", "")
jti = ParseUtil.dictionaryValue(dic, "jti", "")
}
func encode(with nsCoder: NSCoder) {
nsCoder.encode(accessT1, forKey: "accessT1")
nsCoder.encode(t1Type, forKey: "t1Type")
nsCoder.encode(refreshT1, forKey: "refreshT1")
nsCoder.encode(expiresIn, forKey: "expiresIn")
nsCoder.encode(scope, forKey: "scope")
nsCoder.encode(jti, forKey: "jti")
}
}
It worked fine on the original target, cdx-ios
. Can anybody help me? Thank you.
I'm trying to create a new target duplicated from the main target (
cdx_ios
) calledcdx-ios-dev02
.
I think the clue to the answer is in the error message:
cannot decode object of class (cdx_ios.AuthObject) for key (root) because
By default, in an target, the module name for types you declare is the target name, so it's expecting cdx_ios_dev02.AuthObject
, not cdx_ios.AuthObject
to be in the archive you're trying to read.
Presunably you created that archive with the other target.
(There are other ways of configuring the targets that could cause this kind of mixup to occur, but I just picked the easiest one to mention here. 😄 )
I think the likely solution is to make sure your class has a global Obj-C name instead of a module-qualified name:
@objc(AuthObject)
class AuthObject: NSObject, NSCoding {
…
and you would have to recreate your existing archive that already uses the module qualification..
As I said already, there are several ways that module qualification of type names might get in the way, so the actual answer might be a bit different, but I think this is the general area you should be investigating.