• ColumnCodable
  • 文件与代码模版
    • 文件模版
    • 代码模版

    在模型绑定一章中,已经介绍了模型绑定及其内建支持的类型。对于不支持的类,则无法进行字段映射。

    1. class MyClass {
    2. var variable1: String = ""
    3. var variable2: String = ""
    4. }
    5.  
    6. class Sample: TableCodable {
    7. var myClass: MyClass? = nil // 编译错误,myClass 无法进行字段映射
    8.  
    9. enum CodingKeys: String, CodingTableKey {
    10. typealias Root = Sample
    11. static let objectRelationalMapping = TableBinding(CodingKeys.self)
    12. case myClass
    13. }
    14. }

    而本章将介绍开发者如何进行自定义字段映射类型,同时还将提供文件模版和代码模版以简化定义的操作。

    ColumnCodable

    自定义类需要支持字段映射并不复杂,只需实现 ColumnCodable 协议皆可。ColumnCodableColumnEncodableColumnDecodable 组成,以下是它们的原型:

    1. public protocol ColumnCodableBase {
    2. static var columnType: ColumnType {get}
    3. }
    4.  
    5. public protocol ColumnEncodable: Encodable, ColumnCodableBase {
    6. func archivedValue() -> FundamentalValue // 将该类型转换为基础类型
    7. }
    8.  
    9. public protocol ColumnDecodable: Decodable, ColumnCodableBase {
    10. init?(with value: FundamentalValue) // 将基础类型转换为该类型
    11. }

    FundamentalValue 为该类在数据库中存储的形式。例如,Int 可以以 Int64 的形式存储。Date 既可以以时间戳 Double 的形式存储,也可以以 JSON 序列化后 Data 的形式存储。这需要开发者自行确定。而 archivedValueinit?(with:) 实际上就是序列化和反序列化的过程。

    以上述的 MyClass 为例,可以以 JSON 的方式对其进行存储,并支持字段映射。JSON 的输出为 Data,因此其可以实现为:

    1. // 错误示例,请勿参照
    2. class MyClass: ColumnCodable {
    3. var variable1: String
    4. var variable2: String
    5.  
    6. static var columnType: ColumnType {
    7. return .BLOB
    8. }
    9.  
    10. required init?(with value: FundamentalValue) {
    11. let data = value.dataValue
    12. guard data.count > 0 else {
    13. return nil
    14. }
    15. guard let dictionary = try? JSONDecoder().decode([String: String].self, from: data) else {
    16. return nil
    17. }
    18. variable1 = dictionary["variable1"] as? String ?? ""
    19. variable2 = dictionary["variable2"] as? String ?? ""
    20. }
    21.  
    22. func archivedValue() -> FundamentalValue {
    23. guard let data = try? JSONEncoder().encode([
    24. "variable1": variable1,
    25. "variable2": variable2]) else {
    26. return FundamentalValue(data)
    27. }
    28. return FundamentalValue(nil)
    29. }
    30. }

    由于 JSON 是比较常用的序列化和反序列化方式,因此 WCDB Swift 基于 Swift 4.0 的 Codable 协议,实现了默认的 ColumnJSONCodable

    1. class MyClass: ColumnJSONCodable {
    2. var a: String = ""
    3. var b: String = ""
    4. }

    文件与代码模版

    自定义字段映射类型中,有部分是格式固定的代码,因此,WCDB Swift 提供了文件模版和代码模版两种方式,以简化操作。

    文件和代码模版都在源代码的 tools/templates 目录下,链入 WCDB Swift 时会自动安装。

    文件模版

    文件模版安装完成后,在 Xcode 的菜单 File -> New -> File… 中创建新文件,选择 ColumnCodable

    在弹出的菜单中依次

    • 输入文件名
    • 选择 Language 为 Swift
    • 选择对应的基础类型
      ColumnCodableXctemplate

    代码模版

    在代码文件中的任意位置,输入 ColumnCodableClass 后选择对应基础类型的代码模版即可。

    ColumnCodableSnippet

    文件和代码模版都是以 class 作为例子的,实际上 struct 甚至 enum 都可以作为字段映射的类型。