【发布时间】:2018-12-26 13:47:25
【问题描述】:
有一种方法可以使我的 on code 函数适用于我的可编码结构, 我面临的问题是我可以从网络对其进行编码,但不能从用户默认值解码。这是结构的实现。
struct profile: Codable{
var id: Int?
var firstName: String?
var lastName: String?
var description: String?
var gender: String?
var birthDate: Date?
var smoke: Bool?
var findHouse: Bool?
var hasRoom: Bool?
var sociable: Int?
var ordered: Int?
var athlete: Int?
var party: Int?
var domestic:Int?
var gamer: Int?
var usersId: Int?
var imageId: Int?
var createdAt: Date?
var updatedAt: Date?
var image: imageModel?
var tags: [String]?
enum CodingKeys: String, CodingKey {
case id
case firstName = "first_name"
case lastName = "last_name"
case description
case gender
case birthDate = "birth_date"
case smoke
case findHouse = "find_house"
case hasRoom = "has_room"
case sociable
case ordered
case athlete
case party
case domestic
case gamer
case usersId = "users_id"
case imageId = "image_id"
case createdAt = "created_at"
case updatedAt = "updated_at"
case image
case tags
}
init(){
}
init(from decoder: Decoder) throws {
print("going to decode from decoder showing results")
let values = try decoder.container(keyedBy: CodingKeys.self)
self.id = (try values.decodeIfPresent(Int.self, forKey: .id))
print("id value \(self.id)")
self.firstName = (try values.decodeIfPresent(String.self, forKey: .firstName))
print("name value \(self.firstName)")
self.lastName = (try values.decodeIfPresent(String.self, forKey: .lastName))
print("lastname value \(lastName)")
self.description = (try values.decodeIfPresent(String.self, forKey: .description))
print("description value \(description)")
self.gender = (try values.decodeIfPresent(String.self, forKey: .gender))
print("gender value \(gender)")
if let date = try values.decodeIfPresent(String.self, forKey: .birthDate){
print("date value \(date)")
self.birthDate = Date(fromString: String(date.dropLast(10)), format: .custom("yyyy-MM-dd"))
print("after conversion \(self.birthDate)")
}else{
self.birthDate = nil
}
self.smoke = (try values.decodeIfPresent(Int.self, forKey: .smoke)) == 0 ? false : true
print("smoke value \(smoke)")
self.findHouse = (try values.decodeIfPresent(Int.self, forKey: .findHouse)) == 0 ? false : true
print("findhouse value \(findHouse)")
self.hasRoom = (try values.decodeIfPresent(Int.self, forKey: .hasRoom)) == 0 ? false : true
print("has romm value \(hasRoom)")
self.sociable = (try values.decodeIfPresent(Int.self, forKey: .sociable))
print("sociable value\(sociable)")
self.ordered = (try values.decodeIfPresent(Int.self, forKey: .ordered))
print("orderder value \(ordered)")
self.athlete = (try values.decodeIfPresent(Int.self, forKey: .athlete))
print("athlete value \(athlete)")
self.party = (try values.decodeIfPresent(Int.self, forKey: .party))
self.domestic = (try values.decodeIfPresent(Int.self, forKey: .domestic))
self.gamer = (try values.decodeIfPresent(Int.self, forKey: .gamer))
self.usersId = (try values.decodeIfPresent(Int.self, forKey: .usersId))
self.imageId = (try values.decodeIfPresent(Int.self, forKey: .imageId))
if let date = try values.decodeIfPresent(String.self, forKey: .createdAt){
self.createdAt = Date(fromString: String(date.dropLast(10)), format: .custom("yyyy-MM-dd"))
}else {
self.createdAt = nil
}
if let date = try values.decodeIfPresent(String.self, forKey: .updatedAt){
self.updatedAt = Date(fromString: String(date.dropLast(10)), format: .custom("yyyy-MM-dd"))
}else{
self.updatedAt = nil
}
self.image = (try values.decodeIfPresent(imageModel.self, forKey: .image))
self.tags = (try values.decodeIfPresent([String].self, forKey: .tags))
}
}
这是保存到 userdefaults.standard 的代码:
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(requestManager.instance.user) {
UserDefaults.standard.set(encoded, forKey: "user")
if let json = String(data: encoded, encoding: .utf8) {
print("reading value in userDefault \(json)")
}
}
所以当我尝试使用此代码从 userDefaults 解码时:
let decoder = JSONDecoder()
if let user = UserDefaults.standard.data(forKey: "user"){
print("data for user \(user)")
do{
let question = try decoder.decode(profile.self, from: user)
print("birthDate from decoder \(question.birthDate)")
print("id from decoder \(question.id)")
print("name from decoder \(question.firstName)")
if question.id != nil {
print("the id is not Nil \(question)")
requestManager.instance.user = question
}
}catch{
print(error.localizedDescription)
print("el valor de birthDate in \(requestManager.instance.user.birthDate)")
}
}
在此之后,我在控制台中收到了这些消息
将从解码器解码。 id 值 可选(3)。 名称值可选(“Yoel”)。 由于格式不正确,无法读取数据。
我猜是birthDate、createdAt和updatedAt字段中的日期类型。
所以我想尝试的是创建一个自定义编码器,因为在解码器中需要一个字符串并且应该返回一个日期值。
【问题讨论】:
-
如果您更改
init(from中的类型,您必须在encode(中执行相反的操作 -
不需要创建编码功能,我已经完成了编码功能,但这并不能解决保存到用户默认设置的主要问题。
-
确实有必要。例如,您将
hasRoom编码为Bool(使用合成编码器),但您将其解码为Int,这会导致类型不匹配。尊重,没有冒犯,但你的整个结构是一团糟。 ?????? -
这里的问题是我从端点得到的,如果是布尔值 true 或 false,那会很好,但确实是布尔值 0 和 1,所以如果我这样做,那么 Int 必须对只有 0 和 1 所以很明显一个布尔值只是没有从端点恢复
-
尽管如此,如果您使用完整的
Codable协议,所有编码和解码类型都必须匹配。
标签: swift nsuserdefaults codable