【问题标题】:How to implement Core Data Transformable type for [[Int?]] and [[String?]]如何为 [[Int?]] 和 [[String?]] 实现 Core Data 可转换类型
【发布时间】:2022-01-11 04:17:23
【问题描述】:

对于我的问题,我在 GitHub 上准备了 a simple SwiftUI project

一个后端向我的应用发送以下 JSON 数据,代表一个 15 x 15 字母的游戏:

{
    "gid":266,
    "letters":[
        [null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],
        [null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],
        [null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],
        [null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],
        [null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],
        [null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],
        [null,null,null,null,null,null,null,"H", null,null,null,null,null,null,null],
        [null,null,null,null,null,null,null,"U", null,null,null,null,null,null,null],
        [null,null,null,null,null,null,null,"E", null,null,null,null,null,null,null],
        [null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],
        [null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],
        [null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],
        [null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],
        [null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],
        [null,null,null,null,null,null,null,null,null,null,null,null,null,null,null]
    ],
    "values":[
        [null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],
        [null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],
        [null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],
        [null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],
        [null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],
        [null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],
        [null,null,null,null,null,null,null, 4,  null,null,null,null,null,null,null],
        [null,null,null,null,null,null,null, 1,  null,null,null,null,null,null,null],
        [null,null,null,null,null,null,null, 1,  null,null,null,null,null,null,null],
        [null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],
        [null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],
        [null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],
        [null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],
        [null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],
        [null,null,null,null,null,null,null,null,null,null,null,null,null,null,null]
    ],
    "tiles":[
        {"col": 8, "row": 7, "value": 1, "letter": "E"},
        {"col": 7, "row": 7, "value": 1, "letter": "U"},
        {"col": 6, "row": 7, "value": 4, "letter": "H"}
    ]
}

您可以看到lettersvaluesString?Int? 的二维数组,这就是我在用于JSON 解析的GameModel.swift 中定义它们的方式:

struct GameModel: Codable, Identifiable {
    var id: Int32 { gid }
    let gid: Int32
    let letters: [[String?]]
    let values: [[Int32?]]
    let tiles: [TileModel]? // the previous move as an array

    // create a new Core Data entity and copy the properties
    func toEntity(viewContext: NSManagedObjectContext) -> GameEntity {
        let gameEntity = GameEntity(context: viewContext)
        gameEntity.gid = self.gid
        gameEntity.letters = self.letters
        gameEntity.values = self.values
        gameEntity.tiles = self.tiles
        return gameEntity
    }
}

struct TileModel: Codable {
    let col: Int
    let row: Int
    let value: Int
    let letter: String
}

我正在尝试使用 Transformable 核心数据类型来解析它们,因此我已将这 3 行添加到 Persistence.swift

let container: NSPersistentContainer

init(inMemory: Bool = false) {
    ValueTransformer.setValueTransformer(ValuesToDataTransformer(), forName: .valuesToDataTransformer)
    ValueTransformer.setValueTransformer(LettersToDataTransformer(), forName: .lettersToDataTransformer)
    ValueTransformer.setValueTransformer(TilesToDataTransformer(), forName: .tilesToDataTransformer)

    container = NSPersistentContainer(name: "TransApp")

我还添加了 3 个文件:

我的问题是我的自定义 ValueTransformer 子类无法编译。

错误是:

静态方法 'unarchivedObject(ofClass:from:)' 要求 '[[Int32?]]' 符合 'NSCoding'

其他 2 个也类似。

【问题讨论】:

标签: ios swift core-data


【解决方案1】:

这是避免Transformable 的完全不同的方法。它仅将 TileModel 数组保存为 JSON 字符串,并使用计算属性来创建网格并将自定义类型与 JSON 相互转换。

其实你根本不需要解码网格。

  • 在实体中将tiles 声明为String

    @NSManaged public var tiles: String?
    
  • 添加一个计算属性以将 TileModel 数组转换为 JSON

    var tileArray: [TileModel]? {
        get {
            guard let data = tiles?.data(using: .utf8) else { return nil }
            return try? JSONDecoder().decode([TileModel].self, from: data)
        }
        set {
            guard let data = try? JSONEncoder().encode(newValue) else { tiles = nil; return }
            tiles = String(data: data, encoding: .utf8)
        }
    }
    
  • 以及创建网格的计算属性,没有理由将它们保存在实体中

    var values : [[Int?]] {
          var grid : [[Int?]] = [
              [nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil],
              [nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil],
              [nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil],
              [nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil],
              [nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil],
              [nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil],
              [nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil],
              [nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil],
              [nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil],
              [nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil],
              [nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil],
              [nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil],
              [nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil],
              [nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil],
              [nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil]]
          tileArray?.forEach{ grid[$0.col][$0.row] = $0.value }
          return grid
      }
    
    var letters : [[String?]] {
          var grid : [[String?]] = [
              [nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil],
              [nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil],
              [nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil],
              [nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil],
              [nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil],
              [nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil],
              [nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil],
              [nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil],
              [nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil],
              [nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil],
              [nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil],
              [nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil],
              [nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil],
              [nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil],
              [nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil]]
          tileArray?.forEach{ grid[$0.col][$0.row] = $0.letter }
          return grid
      }
    

【讨论】:

  • 啊,我看到我使用了一个不幸的示例数据,您认为瓦片数据复制了字母/值数据。虽然在我的real game 中,图块仅保存 last 移动,而字母/值在游戏板上保存 所有 字母图块......仍然感谢您的回复,点赞。 “添加计算属性”是指在 Xcode 中选择“创建 NSManaged 子类...”并将代码放入生成的类中吗?
  • 可以,或者写一个类的扩展。
  • 谢谢,我已经添加了GameEntity+Extensions.swift,它似乎有效。
猜你喜欢
  • 2016-06-08
  • 2011-05-22
  • 2016-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多