Codable - arrayPropety [AnyObject]: Reference to member 'data' cannot be resolved without a contextual type

Viewed 366

Setting up Codable Class. The array of AnyObjects is creating a compilation error:

Reference to member 'data' cannot be resolved without a contextual type

class ClassA<T>: NSObject, Codable {

    // MARK: - Properties

    let title: String
    let data: [T] // data is an array of either Codable objects of ClassB or ClassC. 

    // MARK: - Keyes

    private enum CodingKeys: String, CodingKey {
        case title
        case data
    }

    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)

        title = try container.decode(String.self, forKey: .title)
        data = [T]()
    }

    func encode(to encoder: Encoder) throws {

        var container = encoder.container(
            keyedBy: CodingKeys.self
        )

        try container.encode(title, forKey: .title)
        try container.encode(data, forKey: .data) // Compilation error: Reference to member 'data' cannot be resolved without a contextual type
    }
}
2 Answers

Data type T must conform to Encodable/Codable change

class ClassA<T:Codable>: NSObject, Codable {

the compiler won't know whether the array generic element conform to Encodable or not , hence the error

The encode(_:, forKey:) method needs a type conforming to Encodable, otherwise how could it know how to encode that input argument? So you either need to change your generic type parameter to require Encodable/Codable conformance or don't encode the data variable if it doesn't need to be part of your JSON (as it seems it isn't part of the decoded JSON anyways).

Simply make ClassB and ClassC conform to Codable too and then changing the type constraint won't be an issue and you won't even need the custom init(from:) and encode(to:) methods.

class ClassA<T: Codable>: Codable {

    // MARK: - Properties
    let title: String
    let data: [T] // data is an array of either Codable objects of ClassB or ClassC. 
}

Unrelated to your issue, but you shouldn't make Swift classes inherit from NSObject unless you need it for Obj-C interoperability. Swift classes don't need to inherit from a base class unlike in Obj-C.

Related