web-dev-qa-db-fra.com

Le type de protocole ne peut pas se conformer au protocole car seuls les types concrets peuvent se conformer aux protocoles

Dans l'application, nous avons deux types d'autocollants, String et Bitmap. Chaque pack d'autocollants peut contenir les deux types. Voici comment je déclare les modèles:

// Mark: - Models

protocol Sticker: Codable {
}

public struct StickerString: Sticker,  Codable, Equatable {
    let fontName: String
    let character: String
}

public struct StickerBitmap: Sticker,  Codable, Equatable {
    let imageName: String
}

Une fois que l'utilisateur a choisi des autocollants et les a utilisés, nous voulons enregistrer les autocollants dans UserDefaults afin que nous puissions lui montrer l'onglet Autocollant "Récemment utilisé". J'essaie de décoder le tableau [Sticker] Enregistré:

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

Mais j'obtiens l'erreur de compilation suivante:

Protocol type 'Sticker' cannot conform to 'Decodable' because only concrete types can conform to protocols

Je ne comprends pas pourquoi j'ai déclaré Sticker comme Codable qui implémente également Decodable. Toute aide serait très appréciée!

7
Roi Mulia

ce qui se passe ici est assez explicite


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

mais supposons que vous pouvez passer un protocole dans votre protocole

protocol Sticker: Codable {
}

où sont les propriétés que vous attendez Swift à décoder à partir des données?

vous avez ajouté les propriétés dans

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
}

Voici ce que je vous suggère de faire tant que vous voulez que le type que vous souhaitez décoder soit dynamique

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
    }

}
  • à travers cette classe, vous pouvez passer n'importe quel type ou même liste conforme à Codable
  • alors vous découplerez la vérification de type du processus de décodage en utilisant la méthode ci-dessous
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 */
            }
        }
    }
0
karem_gohar