簡體   English   中英

Codable class 不符合 Decodable 協議

[英]Codable class does not conform to protocol 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 的 decode init 會將書簽引用設置為自身。

由於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)
    }
}

為什么我收到“類型‘書簽’不符合‘可解碼’協議”的錯誤消息

這是因為出版不可解碼(你還沒有表現出它是什么,所以這是很難說),或者因為的weak上指定publication

無論哪種方式,修復都很容易:您只需要實現init(from:)即可完成 Decodable 的實現; 編譯器只是告訴你這個實現不能被綜合。

事后看來,當我嘗試將Codable設置Codable NSNumber 類型變量組成的類時,我收到了類似的錯誤。 見下圖:

在此處輸入圖片說明

NSNumber更改為原始數據類型Int解決了該問題。 見下文:

在此處輸入圖片說明

我猜這對於需要橋接到 Swift 標准庫值類型(例如 NSString、NSArray 等)的其他數據類型可能是正確的

您可能會收到此消息的另一個原因是您的 CodingKeys 枚舉不是詳盡無遺的。 如果您在數據類型中有三個屬性,那么您的 CodingKeys 枚舉也需要有三個屬性/名稱案例。

僅僅因為您的 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 方法,因為現在可以合成實現。

在類似的情況下,我遇到了同樣的問題,因為我的CodingKeys 中的變量名與類變量不同。 見下文

在此處輸入圖片說明

任何可編碼的類都必須具有可編碼的所有屬性。 標准庫類型(如 String、Int、Double 和 Foundation 類型(如 Date、Data 和 UR)確認可編碼協議,但有些則沒有。

例如,Note 類具有確認可編碼協議的字符串的所有屬性,因此沒有錯誤: 字符串具有可編碼的協議,因此類沒有錯誤

但是 UIImage 不確認可編碼協議,因此會引發錯誤: Uiimage 沒有編碼它顯示錯誤

簡而言之,在實現 Codable 時,所有非原始數據類型(平均類類型或可能是 Objective-c 類)的屬性都必須是 Codable。

   weak var publication: Publication?

在這種情況下,發布是類類型,因此發布必須已實現 Codable

您可以省略編碼鍵枚舉中的屬性,前提是它具有默認值。

來自蘋果文檔

如果在解碼實例時不存在這些屬性,或者某些屬性不應包含在編碼表示中,則忽略 CodingKeys 枚舉中的屬性。 CodingKeys 中省略的屬性需要一個默認值,以便其包含的類型自動符合 Decodable 或 Codable。

有點愚蠢,但以防萬一它對其他人有幫助。 我收到這個錯誤是因為我把enum CodingKeys: CodingKeys而不是enum CodingKeys: CodingKey

我有一個類似的問題,我偶然發現了這個修復程序。 由於我是 Swift 的新手,我不確定它為什么有效! 如果有人知道,我將不勝感激。

我改變了這個:

let id, type: Int

對此:

let id: Int
let type: Int

我可以通過將結構名稱更改為我想要的結構的當前swift文件來解決此問題。 例如,我要將其放入BookmarkModel.swift ,因此鍵入以下內容:

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

更改為此:

class BookmarkModel: 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
       }
    }

如果您已經嘗試了上述所有解決方案但仍然無法修復錯誤,那么我認為這可能是因為您用於數據 class 字段的數據類型。

在問題中,他們使用了 1 個字段weak var publication: Publication? ,並且如果您具有相同類型的 class 結構,那么也許您應該檢查該Publication數據 class 是否符合Codable class。

因為對於孩子 class 也必須遵守相同的協議,因為 tit 的字段也應該是可編碼和可去除的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM