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!
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
}
}
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 */
}
}
}