Skip to content

Swift 自定义字段映射类型

sanhuazhang edited this page Jan 23, 2018 · 8 revisions

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

class MyClass {
	var variable1: String = ""
	var variable2: String = ""
}

class Sample: TableCodable {
    var myClass: MyClass? = nil // 编译错误,myClass 无法进行字段映射
    
    enum CodingKeys: String, CodingTableKey {
        typealias Root = Sample
        static let objectRelationalMapping = TableBinding(CodingKeys.self)
        case myClass
    }
}

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

ColumnCodable

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

protocol ColumnEncodable {
    associatedtype FundamentalType: FundamentalColumnType // 基础类型,必须为 Int32, Int64, Double, String 或 Data
    func archivedValue() -> FundamentalType? // 将该类型转换为基础类型
}

protocol ColumnDecodable {
    associatedtype FundamentalType: FundamentalColumnType // 基础类型,必须为 Int32, Int64, Double, String 或 Data
    init?(with value: FundamentalType) // 将基础类型转换为该类型
}

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

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

// 错误示例,请勿参照
class MyClass: ColumnCodable {
    var variable1: String
    var variable2: String

    typealias FundamentalType = Data

    required init?(with value: Data) {
        guard value.count > 0 else {
            return nil
        }
        guard let dictionary = try? JSONDecoder().decode([String: String].self, from: value) else {
            return nil
        }
        variable1 = dictionary["variable1"] as? String ?? ""
        variable2 = dictionary["variable2"] as? String ?? ""
    }

    func archivedValue() -> Data? {
        return try? JSONEncoder().encode([
            "variable1": variable1,
            "variable2": variable2])
    }
}

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

class MyClass: ColumnJSONCodable {
	var a: String = ""
	var b: String = ""
}

文件与代码模版

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

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

文件模版

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

在弹出的菜单中依次

  1. 输入文件名
  2. 选择 Language 为 Swift
  3. 选择对应的基础类型

ColumnCodableXctemplate

代码模版

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

ColumnCodableSnippet

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

Clone this wiki locally