2
votes

When I try to access the value of "value" for example to use it in a label.text, I get an error

Cannot assign value of type 'MyValue?' to type 'String?'

When I print the value to the terminal, it says ...

unknown context at 0x109d06188).MyValue.string...

How can solve this problem?

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)
        }
    }
}
2
It looks like title doesn't match the body of the question at all. Can you fix it?user28434'mstep
Show your code where you are assigning myValue to some attributeKamran

2 Answers

1
votes

You can get string values for your label by conforming to rawRepresentable protocol:

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
0
votes

To get the associated values in the enum you could add two computed properties in 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
}

Or switch on value like in the encode method

 switch root.value {
    case .string(let string): // do something with `string`
    case .innerItem(let innerItem):  // do something with `innerItem`
 }

Or simply use if case

if case .string(let string) = root.value { someLabel.text = string }