使用编码器与 Json 处理对象初始化?
Handling Object init with coder vs from Json?
我有一个 init 方法可以使用 JSON 数据初始化我的模型,但是当我还想将此对象存储在 NSUserDefaults 中时,我需要创建 acoder 和 adecoder init 方法。
我收到错误:
Cannot invoke 'UserProfileModel.init' with an argument list of type '(apiKey: String, userID: String, userEmail: String, lastName: String, firstName: String, company: String, userImage: String, jobTitle: String)'
解码器的初始化是:
required convenience init(coder aDecoder: NSCoder) {
let apiKey = aDecoder.decodeObject(forKey: "apiKey") as! String
let userID = aDecoder.decodeObject(forKey: "userID") as! String
let userEmail = aDecoder.decodeObject(forKey: "userEmail") as! String
let lastName = aDecoder.decodeObject(forKey: "lastName") as! String
let firstName = aDecoder.decodeObject(forKey: "firstName") as! String
let company = aDecoder.decodeObject(forKey: "company") as! String
let userImage = aDecoder.decodeObject(forKey: "userImage") as! String
let jobTitle = aDecoder.decodeObject(forKey: "jobTitle") as! String
self.init(apiKey: apiKey, userID: userID, userEmail: userEmail, lastName: lastName, firstName: firstName, company: company, userImage: userImage, jobTitle: jobTitle)
}
但我已经有了这个初始化:
init?(_ json: JSON) {
// Map API Key from top level
guard let apiKey = json["apikey"].string
else { return nil }
// assign user
guard let userID = json["user"]["id"].string,
let userEmail = json["user"]["email"].string,
let lastName = json["user"]["lastname"].string,
let firstName = json["user"]["firstname"].string
else { return nil }
// assign optionals to user
let company = json["user"]["company"].string
let userImage = json["user"]["image"].string
let jobTitle = json["user"]["jobtitle"].string
// Assign to model properties
self.apiKey = apiKey
self.userID = userID
self.userEmail = userEmail
self.lastName = lastName
self.firstName = firstName
self.company = company
self.userImage = userImage
self.jobTitle = jobTitle
}
如何在不引发此错误的情况下使两者协调一致?
使您的解码器函数成为必需的 init 而不是方便的 init。
required init(coder aDecoder: NSCoder) {
self.apiKey = aDecoder.decodeObject(forKey: "apiKey") as! String
self.userID = aDecoder.decodeObject(forKey: "userID") as! String
self.userEmail = aDecoder.decodeObject(forKey: "userEmail") as! String
self.lastName = aDecoder.decodeObject(forKey: "lastName") as! String
self.firstName = aDecoder.decodeObject(forKey: "firstName") as! String
self.company = aDecoder.decodeObject(forKey: "company") as! String
self.userImage = aDecoder.decodeObject(forKey: "userImage") as! String
self.jobTitle = aDecoder.decodeObject(forKey: "jobTitle") as! String
}
就这些:)希望对您有所帮助
这是什么问题?
在iOS中,所有便利的init最终都应该调用指定的初始化器。在您的情况下,您已经有一个指定的初始化器,它接受 jSON。现在两个解决方案。
声明一个指定的 init,它采用所有值,例如您在代码 init(coder aDecoder: NSCoder)
最后一行中使用的值,并使您的 init(_ json: JSON)
也是一个方便的初始化程序,最后在两个 init(coder aDecoder: NSCoder)
和 init(_ json: JSON)
调用指定的初始化器
否则只需使用我上面指定的第二种简单方法。
编辑:
如果我要求它,我如何使用 JSON 进行初始化?我也需要这样做吗?
是的,您需要编写 required init(coder aDecoder: NSCoder) {
,因为您正在确认 NSCoding
协议,而 NSCoding 协议希望您实现此初始化。因此它是必需的初始化。
因为你的 init(_ json: JSON) {
是你的 class 的指定初始值设定项。
指定初始化器和必需初始化器有什么区别?
请阅读:
正如它明确总结的那样
- 不需要指定必需的初始化器。
- 不一定需要指定的初始化器。
我有一个 init 方法可以使用 JSON 数据初始化我的模型,但是当我还想将此对象存储在 NSUserDefaults 中时,我需要创建 acoder 和 adecoder init 方法。
我收到错误:
Cannot invoke 'UserProfileModel.init' with an argument list of type '(apiKey: String, userID: String, userEmail: String, lastName: String, firstName: String, company: String, userImage: String, jobTitle: String)'
解码器的初始化是:
required convenience init(coder aDecoder: NSCoder) {
let apiKey = aDecoder.decodeObject(forKey: "apiKey") as! String
let userID = aDecoder.decodeObject(forKey: "userID") as! String
let userEmail = aDecoder.decodeObject(forKey: "userEmail") as! String
let lastName = aDecoder.decodeObject(forKey: "lastName") as! String
let firstName = aDecoder.decodeObject(forKey: "firstName") as! String
let company = aDecoder.decodeObject(forKey: "company") as! String
let userImage = aDecoder.decodeObject(forKey: "userImage") as! String
let jobTitle = aDecoder.decodeObject(forKey: "jobTitle") as! String
self.init(apiKey: apiKey, userID: userID, userEmail: userEmail, lastName: lastName, firstName: firstName, company: company, userImage: userImage, jobTitle: jobTitle)
}
但我已经有了这个初始化:
init?(_ json: JSON) {
// Map API Key from top level
guard let apiKey = json["apikey"].string
else { return nil }
// assign user
guard let userID = json["user"]["id"].string,
let userEmail = json["user"]["email"].string,
let lastName = json["user"]["lastname"].string,
let firstName = json["user"]["firstname"].string
else { return nil }
// assign optionals to user
let company = json["user"]["company"].string
let userImage = json["user"]["image"].string
let jobTitle = json["user"]["jobtitle"].string
// Assign to model properties
self.apiKey = apiKey
self.userID = userID
self.userEmail = userEmail
self.lastName = lastName
self.firstName = firstName
self.company = company
self.userImage = userImage
self.jobTitle = jobTitle
}
如何在不引发此错误的情况下使两者协调一致?
使您的解码器函数成为必需的 init 而不是方便的 init。
required init(coder aDecoder: NSCoder) {
self.apiKey = aDecoder.decodeObject(forKey: "apiKey") as! String
self.userID = aDecoder.decodeObject(forKey: "userID") as! String
self.userEmail = aDecoder.decodeObject(forKey: "userEmail") as! String
self.lastName = aDecoder.decodeObject(forKey: "lastName") as! String
self.firstName = aDecoder.decodeObject(forKey: "firstName") as! String
self.company = aDecoder.decodeObject(forKey: "company") as! String
self.userImage = aDecoder.decodeObject(forKey: "userImage") as! String
self.jobTitle = aDecoder.decodeObject(forKey: "jobTitle") as! String
}
就这些:)希望对您有所帮助
这是什么问题?
在iOS中,所有便利的init最终都应该调用指定的初始化器。在您的情况下,您已经有一个指定的初始化器,它接受 jSON。现在两个解决方案。
声明一个指定的 init,它采用所有值,例如您在代码 init(coder aDecoder: NSCoder)
最后一行中使用的值,并使您的 init(_ json: JSON)
也是一个方便的初始化程序,最后在两个 init(coder aDecoder: NSCoder)
和 init(_ json: JSON)
调用指定的初始化器
否则只需使用我上面指定的第二种简单方法。
编辑:
如果我要求它,我如何使用 JSON 进行初始化?我也需要这样做吗?
是的,您需要编写 required init(coder aDecoder: NSCoder) {
,因为您正在确认 NSCoding
协议,而 NSCoding 协议希望您实现此初始化。因此它是必需的初始化。
因为你的 init(_ json: JSON) {
是你的 class 的指定初始值设定项。
指定初始化器和必需初始化器有什么区别?
请阅读:
正如它明确总结的那样
- 不需要指定必需的初始化器。
- 不一定需要指定的初始化器。