web-dev-qa-db-ja.com

CodableクラスはプロトコルDecodableに準拠していません

「タイプ「ブックマーク」がプロトコル「デコード可能」に適合していません」というエラーメッセージが表示されるのはなぜですか?

class Bookmark: Codable {
   weak var publication: Publication?
   var indexPath: [Int]
   var locationInText = 0

   enum CodingKeys: String, CodingKey {
      case indexPath
      case locationInText
   }

   init(publication: Publication?, indexPath: [Int]) {
      self.publication = publication
      self.indexPath = indexPath
   }
}

出版物はブックマークを所有しているが、ブックマークはそれが属する出版物を知る必要があるため、出版物変数を保存したくない。 Publicationのデコード初期化は、ブックマーク参照をそれ自体に設定します。

36
Melodius

「タイプ「ブックマーク」がプロトコル「デコード可能」に準拠していません」というエラーメッセージが表示されるのはなぜですか

PublicationがDecodableではないため(それが何であるかを示していないため、わかりにくい)、またはweakpublicationが指定されているためです。

どちらにしても、簡単に修正できます。Decodeableの実装を完了するには、init(from:)を実装するだけです。コンパイラは、この実装を合成できないことを単に伝えています。

23
matt

コンパイラは、weak参照のために必要なinit(from:)メソッドを合成できないため、自分で作成する必要があります。

class Bookmark: Codable {
    weak var publication: Publication?
    var indexPath: [Int]
    var locationInText = 0

    private enum CodingKeys: String, CodingKey {
        case indexPath
        case locationInText
    }

    init(publication: Publication?, indexPath: [Int]) {
        self.publication = publication
        self.indexPath = indexPath
    }

    required init(from decoder:Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        indexPath = try values.decode([Int].self, forKey: .indexPath)
        locationInText = try values.decode(Int.self, forKey: .locationInText)
    }
}
34
Dávid Pásztor

後から、NSNumber型の変数で構成されたクラスにCodableを設定しようとすると、同様のエラーを受け取りました。下の画像をご覧ください。

enter image description here

NSNumberをプリミティブデータ型Intに変更すると、問題が解決しました。下記参照:

enter image description here

NSString、NSArrayなどのSwift標準ライブラリ値タイプへのブリッジングを必要とする他のデータタイプについては、これが当てはまると思います。

17
iOSer

このメッセージが表示されるもう1つの理由は、CodingKeys列挙型が網羅的でない場合です。データ型に3つのプロパティがある場合、CodingKeys列挙には3つのプロパティ/名前のケースも必要です。

14
mikepj

CodingKeys列挙型が完全ではないという理由だけで、publicationプロパティを列挙型に追加してそれを実現します。

これを試して:

class Bookmark: Codable {
   weak var publication: Publication?
   var indexPath: [Int]
   var locationInText = 0

   // All your properties should be included
   enum CodingKeys: String, CodingKey {
      case indexPath
      case locationInText
      case publication   // this one was missing
   }
}

実装を合成できるようになったため、initメソッドはもう必要ありません。

3
Wissa

要するに、Codableの実装中、非プリミティブデータ型(平均クラス型またはObjective-Cクラスの可能性がある)であるすべてのプロパティはCodableでなければなりません。

   weak var publication: Publication?

この場合、パブリケーションはタイプクラスであるため、パブリケーションはCodableを実装する必要があります。

2
kalpesh jetani

デフォルト値がある場合にのみ、コーディングキー列挙からプロパティを省略できます。

Apple docs から

インスタンスをデコードするときにプロパティが存在しない場合、または特定のプロパティをエンコードされた表現に含めない場合は、CodingKeys列挙からプロパティを省略します。 CodingKeysから省略されたプロパティは、その包含型がDecodableまたはCodableへの自動適合を受け取るためにデフォルト値を必要とします。

1
Saif

私はこの修正につまずいた同様の問題を抱えていました。私はSwiftを初めて使用するので、なぜそれが機能するのか分かりません!誰もが知っているなら、私は知識を感謝します。

これを変更しました:

let id, type: Int

これに:

let id: Int
let type: Int
0
ThunderGrad