Swift Codable如何使用Any类型?
Swift Codable how to use Any type?
当我尝试访问 "value" 的值(例如在 label.text 中使用它时),出现错误
Cannot assign value of type 'MyValue?' to type 'String?'
当我将值打印到终端时,它说...
unknown context at 0x109d06188).MyValue.string...
如何解决这个问题?
struct Root: Codable {
let description,id: String
let group,groupDescription: String?
let name: String
let value: MyValue
enum CodingKeys: String, CodingKey {
case description = "Description"
case group = "Group"
case groupDescription = "GroupDescription"
case id = "Id"
case name = "Name"
case value = "Value"
}
}
enum MyValue: Codable {
case string(String)
case innerItem(InnerItem)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let x = try? container.decode(String.self) {
self = .string(x)
return
}
if let x = try? container.decode(InnerItem.self) {
self = .innerItem(x)
return
}
throw DecodingError.typeMismatch(MyValue.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for MyValue"))
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .string(let x):
try container.encode(x)
case .innerItem(let x):
try container.encode(x)
}
}
}
要获取枚举中的关联值,您可以在 MyValue
中添加两个计算属性
var stringValue : String? {
guard case .string(let string) = self else { return nil }
return string
}
var innerItemValue : InnerItem? {
guard case .innerItem(let innerItem) = self else { return nil }
return innerItem
}
或者像 encode
方法那样打开 value
switch root.value {
case .string(let string): // do something with `string`
case .innerItem(let innerItem): // do something with `innerItem`
}
或者直接使用if case
if case .string(let string) = root.value { someLabel.text = string }
您可以通过遵守 rawRepresentable 协议获取标签的字符串值:
enum MyValue: Codable, RawRepresentable {
var rawValue: String {
switch self {
case .string(let stringVal):
return stringVal
case .innerItem(let myVal):
return String(describing: myVal)
}
}
typealias RawValue = String
init?(rawValue: String) {
return nil
}
case string(String)
case innerItem(InnerItem)
}
let myVal = MyValue.string("testString")
var strVal: String = myVal.rawValue // testString
当我尝试访问 "value" 的值(例如在 label.text 中使用它时),出现错误
Cannot assign value of type 'MyValue?' to type 'String?'
当我将值打印到终端时,它说...
unknown context at 0x109d06188).MyValue.string...
如何解决这个问题?
struct Root: Codable {
let description,id: String
let group,groupDescription: String?
let name: String
let value: MyValue
enum CodingKeys: String, CodingKey {
case description = "Description"
case group = "Group"
case groupDescription = "GroupDescription"
case id = "Id"
case name = "Name"
case value = "Value"
}
}
enum MyValue: Codable {
case string(String)
case innerItem(InnerItem)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let x = try? container.decode(String.self) {
self = .string(x)
return
}
if let x = try? container.decode(InnerItem.self) {
self = .innerItem(x)
return
}
throw DecodingError.typeMismatch(MyValue.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for MyValue"))
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .string(let x):
try container.encode(x)
case .innerItem(let x):
try container.encode(x)
}
}
}
要获取枚举中的关联值,您可以在 MyValue
var stringValue : String? {
guard case .string(let string) = self else { return nil }
return string
}
var innerItemValue : InnerItem? {
guard case .innerItem(let innerItem) = self else { return nil }
return innerItem
}
或者像 encode
方法那样打开 value
switch root.value {
case .string(let string): // do something with `string`
case .innerItem(let innerItem): // do something with `innerItem`
}
或者直接使用if case
if case .string(let string) = root.value { someLabel.text = string }
您可以通过遵守 rawRepresentable 协议获取标签的字符串值:
enum MyValue: Codable, RawRepresentable {
var rawValue: String {
switch self {
case .string(let stringVal):
return stringVal
case .innerItem(let myVal):
return String(describing: myVal)
}
}
typealias RawValue = String
init?(rawValue: String) {
return nil
}
case string(String)
case innerItem(InnerItem)
}
let myVal = MyValue.string("testString")
var strVal: String = myVal.rawValue // testString