Protocol type cannot conform to protocol because only concrete types can conform to protocols Protocol type cannot conform to protocol because only concrete types can conform to protocols swift swift

Protocol type cannot conform to protocol because only concrete types can conform to protocols


Rather than protocols use generics.

Declare a simple function

func decodeStickers<T : Decodable>(from data : Data) throws -> T{    return try JSONDecoder().decode(T.self, from: data)}

T can be a single object as well as an array.


In your structs drop the Sticker protocol. You can also delete Equatable because it's getting synthesized in structs.

public struct StickerString : Codable {    let fontName: String    let character: String}public struct StickerBitmap : Codable {    let imageName: String}

To decode one of the sticker types annotate the type

let imageStickers = """[{"imageName":"Foo"},{"imageName":"Bar"}]"""    let stickerData = Data(imageStickers.utf8)let recentStickers : [StickerBitmap] = try! decodeStickers(from: stickerData)print(recentStickers.first?.imageName)

and

let stringSticker = """{"fontName":"Times","character":"😃"}"""    let stickerData = Data(stringSticker.utf8)let sticker : StickerString = try! decodeStickers(from: stickerData)print(sticker.character)

To decode an array of StickerString and StickerBitmap types declare a wrapper enum with associated values

enum Sticker: Codable {    case string(StickerString)    case image(StickerBitmap)    init(from decoder: Decoder) throws {        let container = try decoder.singleValueContainer()        do {            let stringData = try container.decode(StickerString.self)            self = .string(stringData)        } catch DecodingError.keyNotFound {            let imageData = try container.decode(StickerBitmap.self)            self = .image(imageData)        }    }    func encode(to encoder: Encoder) throws {        var container = encoder.singleValueContainer()        switch self {            case .string(let string) : try container.encode(string)            case .image(let image) : try container.encode(image)        }    }}

Then you can decode

let stickers = """[{"imageName":"Foo"},{"imageName":"Bar"}, {"fontName":"Times","character":"😃"}]"""let stickerData = Data(stickers.utf8)let recentStickers = try! JSONDecoder().decode([Sticker].self, from: stickerData)print(recentStickers)

In a table view just switch on the enum

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {    let sticker = stickers[indexPath.row]    switch sticker {    case .string(let stringSticker):         let cell = tableView.dequeueReusableCell(withCellIdentifier: "StringStickerCell", for: indexPath) as! StringStickerCell        // update UI        return cell    case .image(let imageSticker):         let cell = tableView.dequeueReusableCell(withCellIdentifier: "ImageStickerCell", for: indexPath) as! ImageStickerCell        // update UI        return cell    }}


what happens here is kind of self explanatory

JSONDecoder().decode(/* swift here is expecting class or struct that conforms to Codable */.self, from: data)

but let us assume that you can pass a protocolin your protocol

protocol Sticker: Codable {}

where is the properties that you are expecting swift to decode from data ?

you added the properties in

public struct StickerString: Sticker,  Codable, Equatable { // it should have redundendant conformance as well as you are conforming to Coddle again    let fontName: String // here is the properties you are expected to be decoded with the coding keys    let character: String // here is the properties you are expected to be decoded with the coding keys}

Here is what I suggest you do as long you want the type you want to decode to be dynamic

class GenericService< /* here you can pass your class or struct that conforms to Codable */ GenericResponseModel: Codable> {func buildObjectFromResponse(data: Data?) -> GenericResponseModel? {        var object : GenericResponseModel?        do {            object = try JSONDecoder().decode(GenericResponseModel.self , from: data!)        } catch (let error){            print(error)        }        return object    }}
  • through this class you can pass any type or even list that conforms to Codable
  • then you will decouple the type checking from the decoding process using the method below
private func handleDecodingTypes (stickers: [Sticker]){        for sticker in stickers {            if sticker is StickerString {                /* do the decoding here */            }            if sticker is StickerBitmap {                /* do the decoding here */            }        }    }


The Sticker protocol is not confirming/implementing the Codable, it is actually inheriting from the Codable. As the error message suggests, Protocols do not conform to other protocols only concrete types do.

protocol Sticker: Codable //This is Protocol inheritance

By stating

public struct StickerString: Sticker

Means that Sticker string conforms to Sticker and the Sticker is child of Codable, so StickerString eventually conforms to Codable. There is no need to state conformance again i.e:

public struct StickerString: Sticker,  Codable //Conformance to Codable is redundant

Now coming to the decoding part.

  let recentStickers = try? JSONDecoder().decode([Sticker].self, from: data)

The decode method needs a concrete type. It doesn't have any information about the underlying type or its attributes because Sticker is just a protocol itself inheriting from Codable that has no properties/attributes.Compiler would not have any problem combining both the StrickerString and StickerBitmap after they've decoded e.g.

let stickerString = try JSONDecoder().decode(StickerString.self, from: data)let stickerBitmap = try JSONDecoder().decode(StickerBitmap.self, from: data)let stickers : [Sticker] = [stickerString, stickerBitmap]