简体   繁体   中英

Swift 4 enum codable

I parse json data from an api. My struct looks like this:

struct ServiceUnit: Codable {
        let description,id: String?
        let group, groupDescription:String?
        let name: String?
        var 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 string = try? container.decode(String.self) {
                self = .string(string)
                return
            }
            if let innerItem = try? container.decode(InnerItem.self) {
                self = .innerItem(innerItem)
                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)
            }
        }
    }

    struct InnerItem: Codable {
        let type, id, name: String

        enum CodingKeys: String, CodingKey {
            case type = "__type"
            case id = "Id"
            case name = "Name"
        }
    }

and the json data looks like this:

    [
  {
  "Description": null,
  "Group": "Beskrivning av enheten",
  "GroupDescription": null,
  "Id": "Description",
  "Name": "Mer om enheten",
  "Value": "Det finns möjlighet till parkering på gatorna runt om, men det är kantstenar och ganska branta backar för att komma upp till lekplatsen.\r\n\r\nUtanför själva lekplatsen finns en gungställning med en plan omväg in. Alla lekredskap står i sandytor, det finns många kanter. Runt hela lekplatsen går ett staket med öppningar i olika riktningar."
  },
  {
  "Description": null,
  "Group": "Bilder och film",
  "GroupDescription": null,
  "Id": "Image",
  "Name": "Huvudbild",
  "Value": {
      "__type": "FileInfo",
      "Id": "8871b3b1-14f4-4054-8728-636d9da21ace",
      "Name": "ullerudsbacken.jpg"
  }
  }
  ]

When the data is loaded, I filter it to get only the result where id = description, and I retried the value of value like this:

let su = serviceUnit.filter{$0.id == "ShortDescription"}
            let description = su[0].value

Then, my problem is that I get this error from Xcode when I want to use the value to fill a label:

Cannot assign value of type MyValue? to type String?

If I print su , I get this:

[stockholmsParks.(unknown context at 0x105c3d098).ServiceUnit(description: nil, id: Optional("ShortDescription"), group: Optional("Beskrivning av enheten"), groupDescription: nil, name: Optional("Introduktion"), value: Optional(stockholmsParks.(unknown context at 0x105c3d0e8).MyValue.string("Regnbågen på höjden. Den här lekplatsen ligger på ett högt berg i naturmark, omgiven av höghus. Det finns en instängslad bollplan och olika lekredskap står placerade efter varandra. Utanför själva lekplatsen finns en gungställning. Det finns också bänkbord i sol och grillplats.")))]

What am I missing???

You need to get the associated value from your enum.

let value = su[0].value
switch value {
    case .string(let description)?:
        yourLabel.text = description
    default:
        break
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM