Swift 模型化使用SQLite3

在iOS中,使用未經(jīng)處理的SQLite庫是一件很痛苦的事情,所以出現(xiàn)了很多封裝后的庫,其中在Swift語言中使用的較為廣泛的庫是SQLite.Swift。使用過的都知道,這個(gè)庫很好,但是不支持模型化轉(zhuǎn)換就很苦惱,正因?yàn)槿绱?,本文所寫的也正是?duì)SQLite.Swift的模型化封裝

使用

  1. 創(chuàng)建的模型實(shí)現(xiàn)SQLiteProtocol協(xié)議即可
import SQLiteManager

class TestModel: NSObject, SQLiteProtocol {}
struct TestModel: SQLiteProtocol {}
  1. 創(chuàng)建模型后即可快速開始數(shù)據(jù)庫操作
/// 插入模型(默認(rèn)不存在會(huì)創(chuàng)建
SQLiteManager.default.insert(testModel)

/// 刪除模型
SQLiteManager.default.delete(testModel)

/// 更新模型數(shù)據(jù)
testModel.name = "Ree"
testModel.create_time = Int(Date().timeIntervalSince1970)
SQLiteManager.default.update(testModel)

/// 查詢模型數(shù)據(jù)
let arr = SQLiteManager.default.select(TestModel.tableName)
let models = arr.map({ TestModel.deserialize(from: $0) })
print("查詢到數(shù)據(jù): \(models)")

/// 刪除數(shù)據(jù)表
SQLiteManager.default.drop(TestModel.tableName)

以下是實(shí)現(xiàn)原理,若想直接使用,請(qǐng)直接訪問Github,或者直接pod安裝

  pod 'JXSQLiteManager'

基礎(chǔ)協(xié)議

首先我們需要準(zhǔn)備一個(gè)通用的協(xié)議來規(guī)定一些通用的屬性,以及轉(zhuǎn)模型時(shí)需要的初始化方法。后續(xù)所有的模型都是實(shí)現(xiàn)該協(xié)議來實(shí)現(xiàn)

public protocol SQLiteProtocol {
    static var tableName: String { get }
    /// 主鍵字段
    var primaryKey: String? { get }
    /// 忽略的字段,不保存
    var ignoreKeys: [String]? { get }
    /// 唯一的字段
    var uniqueKeys: [String]? { get }
    
    init(_ dict: [String: Any])
}

聲明屬性模型

有了基礎(chǔ)協(xié)議后,我們還需要一個(gè)模型來保存反射解析出的屬性列表來記錄當(dāng)前模型有哪些數(shù)據(jù)表屬性


public struct SQLitePropModel {
    public var key: String
    public var value: Any
    /// 是否是主鍵
    public var primary = false
    
    private var option = false
}

通過反射獲取每一列的屬性,可選類型(optional)在數(shù)據(jù)表中即為非必填項(xiàng),并且當(dāng)屬性值為nil時(shí)記錄值為空

    public init(_ key: String, value: Any, primary: Bool) {
        self.key = key
        self.primary = primary
        
        let mirror = Mirror(reflecting: value)
        self.option = mirror.displayStyle == .optional
        // unwrap optional
        if mirror.displayStyle != .optional {
            self.value = value
        }else if mirror.children.count == 0 { self.value = "" }
        else {
            let (_, some) = mirror.children.first!
            self.value = some
        }
    }

支持的數(shù)據(jù)類型對(duì)應(yīng)數(shù)據(jù)庫類型如下

    public var datatype: String {
        let nativeType = type(of: value)
        var datatype = ""
        
        if nativeType is Int.Type || nativeType is Int?.Type {
            datatype = "INTEGER"
        }else if nativeType is Float.Type || nativeType is Double.Type || nativeType is Float?.Type || nativeType is Double?.Type {
            datatype = "REAL"
        }else if nativeType is NSString.Type || nativeType is String.Type || nativeType is Character.Type || nativeType is NSString?.Type || nativeType is String?.Type || nativeType is Character?.Type {
            datatype = "TEXT"
        }else if nativeType is Bool.Type || nativeType is Bool?.Type {
            datatype = "REAL"
        }else{
            assert(true, "sqlType:不支持的類型")
        }
        return datatype
    }

獲取模型屬性

通過數(shù)據(jù)模型反射出對(duì)應(yīng)的數(shù)據(jù)表屬性模型列表,在該方法中處理需要忽略的模型字段以及模型屬性列表

/// 反射保存屬性的model
public struct SQLMirrorModel {
    public static func operateByMirror(object: SQLiteProtocol) -> SQLMirrorModel {
        let mirror = Mirror(reflecting: object)
        var props = [SQLitePropModel]()
        for case let (key?, value) in mirror.children {
            let model = SQLitePropModel(key, value: value, primary: object.primaryKey == key)
            if object.ignoreKeys?.contains(key) == true {
                continue
            }
            props.append(model)
        }
        
        if mirror.displayStyle != .class || mirror.displayStyle != .struct {
            assert(true, "operateByMirror:不支持的類型")
        }
        return SQLMirrorModel(type(of: object).tableName, props: props, primaryKey: object.primaryKey)
    }
}

多有不足,敬請(qǐng)指教??

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容