web-dev-qa-db-ja.com

プロトコルに準拠できるのは具象タイプのみであるため、プロトコルタイプはプロトコルに準拠できません

アプリ内には、文字列とビットマップの2種類のステッカーがあります。各ステッカーパックには、両方のタイプを含めることができます。これは私がモデルを宣言する方法です:

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

ユーザーがいくつかのステッカーを選択して使用した後、UserDefaultsにステッカーを保存して、「最近使用した」ステッカータブを表示できるようにします。保存した[Sticker]配列をデコードしようとしています:

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

しかし、次のコンパイルエラーが発生します。

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

StickerCodableを実装するDecodableとして宣言したので、なぜか理解できません。どんな助けでも大歓迎です!

7
Roi Mulia

ここで何が起こるかは自明です


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

プロトコルでプロトコルを渡すことができると仮定しましょう

protocol Sticker: Codable {
}

期待しているプロパティはどこですかSwiftデータからデコードする?

プロパティを追加しました

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
}

デコードしたい型を動的にしたい限り、私はあなたがすることをお勧めします

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
    }

}
  • このクラスを介して、Codableに準拠する任意のタイプまたはリストを渡すことができます
  • 次に、以下の方法を使用して、型チェックをデコードプロセスから切り離します。
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