美文网首页
iOS数据存储通用配置

iOS数据存储通用配置

作者: lifeLL | 来源:发表于2018-03-27 17:10 被阅读0次
//
//  CacheManage.swift
//  MMore
//
//  Created by life on 2017/4/17.
//  Copyright © 2017年 TT. All rights reserved.
//

import UIKit
import FMDB
import HandyJSON
//MARK:- 存储配置表
public let serializationCache:String = "serializationCache"//存储序列化字段
enum cacheTableName {//表名 :以对应数据库名开头
    case db_login
    case db_status
    case db_useinfo //单聊用户信息
}

class CacheManage: NSObject {
    var databasePath: String!
//    var database: FMDatabase?
    var dataqueue:FMDatabaseQueue?
    //数据库名
    let sql_database = "db.sqlite"
    fileprivate var fileManager: FileManager = FileManager.default
    static let shared: CacheManage = CacheManage()

    override init() { //初始化
        let documentsDirectory = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]) as String
        databasePath = documentsDirectory.appending("/\(sql_database)")
        dataqueue = FMDatabaseQueue.init(path: databasePath)
    }

    //    @discardableResult init(sqlName: String) {//不用单例是因为需要提供建多个数据库 sql_database
    //        super.init()
    //        let documentsDirectory = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]) as String
    //        databasePath = documentsDirectory.appending("/\(sqlName)")
    //        //判断如果数据库存在则不用init
    //        if !fileManager.fileExists(atPath: databasePath) {
    //            dataqueue = FMDatabaseQueue.init(path: databasePath)
    //        }
    //    }
}
extension CacheManage{//表结构
    func getFieldDicWith(tableName:cacheTableName) -> Dictionary<String,String> {
        var dic = [String:String]()
        switch tableName {
        case cacheTableName.db_login:
            dic = [serializationCache:"BLOB","store_id":"TEXT","m_auth":"TEXT","user_name":"TEXT"]
        case cacheTableName.db_status:
            dic = ["aaaa":"TEXT","bbbb":"TEXT","cccc":"TEXT"]
        case cacheTableName.db_useinfo:
            dic = ["nickName":"TEXT","user_id":"TEXT","avator":"TEXT"]
        }

        return dic
    }
}
//MARK:- 按业务扩展对应方法
extension CacheManage {//MARK:- 单聊用户信息
    func getUserInfoByIdHX(userid:String)->UseInfoModel?{
         let arr =  CacheManage.shared.queryDataWith(tableName: .db_useinfo, dataDic:["user_id":userid]) //都会返回一个数组,即使空数组
        if arr.count > 0 {
            //字典转模型
            let dic = arr[0] as! [String:Any]?//一个id对应一个数组元素,即字典
            let useInfoModel = JSONDeserializer<UseInfoModel>.deserializeFrom(dict: dic as NSDictionary?)
            return useInfoModel
        }else{
            return nil
        }
    }
    func saveUserInfoWith(userId:String,avatorUrl:String,nickName:String){
        var userInfoDic = [String:Any]()
        userInfoDic["nickName"] = nickName
        userInfoDic["user_id"] = userId
        userInfoDic["avator"] = avatorUrl
        CacheManage.shared.saveDataWith(tableName: .db_useinfo, dataDic: userInfoDic)

    }
}


//-----------------------------------------------------------------------------
extension CacheManage{ //MARK:- 增删改查原始语句

    /// 创建表
    ///
    /// - Parameters:
    ///   - tableName: 表名
    ///   - fieldDic: 字段
    func creatTable(tableName:cacheTableName,fieldDic:Dictionary<String, String>?) {//创表
        //1.构造字符串字段
        func fieldStrWithDictionary(fieldDic:Dictionary<String, String>) -> String {
            //拼接查询语句
            let dicKey=Array(fieldDic.keys)
            var str:String = ""
            for temp in dicKey {
                str += temp + " " + fieldDic[temp]! + " NOT NULL,"
            }
            //裁剪字符串
            let index = str.index(str.endIndex, offsetBy: -1)
            let fieldStr = str.substring(to: index)
            return fieldStr
        }
        //2.创表
        let fieldStr = fieldStrWithDictionary(fieldDic: fieldDic!)
        let sql = "CREATE TABLE IF NOT EXISTS \(tableName) (id integer PRIMARY KEY, \(fieldStr));"
        dataqueue?.inDatabase { (db:FMDatabase?) in
            if (db?.open())! {
                if !(db?.executeStatements(sql))! {
                    print("Error: \(db?.lastErrorMessage())")
                }
            }
        }
    }

    /// 新增数据
    ///
    /// - Parameters:
    ///   - tableName: 表名
    ///   - dataDic: 新增的数据
    func saveDataWith(tableName:cacheTableName,dataDic:Dictionary<String, Any>) {//增
        //处理字符串
        func getFieldsWith(fieldDic:Dictionary<String, String>,Dic:Dictionary<String, Any>)->(String,String,Array<Any>){
            let fieldKeys=Array(fieldDic.keys)
            var keysStr:String = ""
            var flagStr:String = ""
            var valueArray:Array = [Any]()
            for temp in fieldKeys {
                keysStr +=  temp + ","
                flagStr += "?,"
                valueArray.append(Dic[temp] ?? "")
            }
            let fieldStr = keysStr.subStringLastChar(originalStr: keysStr, num: -1)
            let flaggStr = flagStr.subStringLastChar(originalStr: flagStr, num: -1)
            return (fieldStr,flaggStr,valueArray)
        }
        var serialDic = [String:Any]()
        serialDic = dataDic
        //有序列号字段就序列号,没有就不处理
        if dataDic[serializationCache] != nil {
            let data = NSKeyedArchiver.archivedData(withRootObject: dataDic[serializationCache] ?? "" ) as Data
            serialDic[serializationCache] = data
        }
        //表不存在就创表
        let fieldDic = getFieldDicWith(tableName: tableName)
        creatTable(tableName: tableName, fieldDic: fieldDic)
        dataqueue?.inDatabase({ (db:FMDatabase?) in
            //添加新增语句
            let fieldTuples = getFieldsWith(fieldDic: fieldDic,Dic:serialDic)
            let insertSql = "INSERT INTO \(tableName)(\(fieldTuples.0)) VALUES (\(fieldTuples.1));"
            db?.executeUpdate(insertSql, withArgumentsIn: fieldTuples.2)//传的字段和表的字段要对应才插入成功
        })
    }

    /// 根据指定字段删除 or dic==nil 则删掉表
    ///
    /// - Parameters:
    ///   - tableName: 表名
    ///   - dic: 指定字段及值for字典形式
    func delectDataWith(tableName:cacheTableName,dic:Dictionary<String,Any>? = nil) {//删

        func getFieldsWith(fieldDic:Dictionary<String, String>)->(String){
            let fieldKeys=Array(fieldDic.keys)
            var keysStr:String = ""
            if fieldKeys.count == 1 {
                keysStr += fieldKeys[0] + " = ? "
            }else{
                for temp in fieldKeys {
                    keysStr +=  temp + " = ? and "
                }
                keysStr = keysStr.subStringLastChar(originalStr: keysStr, num: -4)//空格算一个字符
            }
            return keysStr
        }

        dataqueue?.inDatabase({ (db:FMDatabase?) in
            if dic == nil { //删表
                let delectSql = "DELETE FROM \(tableName)"
                db?.executeUpdate(delectSql, withArgumentsIn: nil)
            }else{
                let fieldStringS = getFieldsWith(fieldDic: dic as! Dictionary<String, String>)
                let delectSql = "DELETE FROM \(tableName) WHERE \(fieldStringS)"
                db?.executeUpdate(delectSql, withArgumentsIn: Array(dic!.values))//这里的赋值有漏洞,存在不对应概率
            }

        })
    }

    /// 更新表格字段:根据whereDic更新dataDic
    ///
    /// - Parameters:
    ///   - tableName: 表名
    ///   - dataDic:   修改字段及值
    ///   - whereDic:  查询字段及值
    func updateDataWith(tableName:cacheTableName,dataDic:Dictionary<String, Any>,whereDic:Dictionary<String, Any>){

        func subStr(Dic:Dictionary<String, Any>)->String{
            let Keys=Array(Dic.keys)
            var str = ""
            for temp in Keys {
                str = temp + "=?,"
            }
            str = str.subStringLastChar(originalStr: str, num: -1)
            return str
        }

        dataqueue?.inDatabase({ (db:FMDatabase?) in
            let fieldStr = subStr(Dic: dataDic)
            let whereStr = subStr(Dic: whereDic)

            let qudateSQL = "UPDATE \(tableName) SET \(fieldStr) WHERE \(whereStr)"
            db?.executeUpdate(qudateSQL, withArgumentsIn: Array(dataDic.values) + Array(whereDic.values))
        })
    }

    /// 根据Dic的键值对查询表
    ///
    /// - Parameters:
    ///   - tableName: 表名
    ///   - Dic: 字段和值
    /// - Returns: 字典元素数组
    @discardableResult func queryDataWith(tableName:cacheTableName,dataDic:Dictionary<String, Any>) -> [Any?] {
        //1.
        func getFieldsWith(fieldDic:Dictionary<String, String>)->(String){
            let fieldKeys=Array(fieldDic.keys)
            var keysStr:String = ""
            if fieldKeys.count == 1 {
                keysStr += fieldKeys[0] + " = ? "
            }else{
                for temp in fieldKeys {
                    keysStr +=  temp + " = ? and "
                }
                keysStr = keysStr.subStringLastChar(originalStr: keysStr, num: -4)//空格算一个字符
            }
            return keysStr
        }
        //2.
        let queryStr = getFieldsWith(fieldDic: dataDic as! Dictionary<String, String>)
        var ArgumentDic = [String:Any]()
        var ArgumentArr = [Dictionary<String, Any>]()
        dataqueue?.inDatabase({ (db:FMDatabase?) in
            if (db?.tableExists(String(describing: tableName)))! {//判断表是否存在
                let selectSQL = "SELECT * FROM \(tableName) WHERE \(queryStr)"
                let rs = db?.executeQuery(selectSQL, withArgumentsIn: Array(dataDic.values))
                let fieldDic =  self.getFieldDicWith(tableName: tableName)

                while (rs?.next())! {
                    let Keys = Array(fieldDic.keys)//对应表的字段
                    for temp in Keys {
                        switch fieldDic[temp]! as String {
                        case "TEXT":
                            ArgumentDic[temp] = rs?.string(forColumn: temp)
                        case "BLOB":
                            let data = rs?.data(forColumn: temp)
                            ArgumentDic[temp] = NSKeyedUnarchiver.unarchiveObject(with: data! ) //反序列化
                        case "INTEGER":
                            ArgumentDic[temp] = rs?.int(forColumn: temp)
                        case "DATETIME":
                            ArgumentDic[temp] = rs?.date(forColumn: temp)
                        default:
                            ArgumentDic[temp] = rs?.object(forColumnName: temp)
                        }
                    }
                    ArgumentArr.append(ArgumentDic)

                }
            }
        })
        return ArgumentArr
    }
}


相关文章

网友评论

      本文标题:iOS数据存储通用配置

      本文链接:https://www.haomeiwen.com/subject/fzyscftx.html