import Foundation
import FMDB
/*
1.创建队列
2.创建表格
3.操作数据
*/
//缓存时间
private let MAXDBCACHETIME:TimeInterval = -3 * 24 * 60 * 60
//这个不停创建影响性能
private let dateFormatter =DateFormatter()
class FZSQLLiteManager {
//单例 private init()
staticlet shared = FZSQLLiteManager()
//创建数据库队列
let queue:FMDatabaseQueue
privateinit() {
//s沙盒路径
let dbname ="test.db"
//拼接路径
var path =NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask,true)[0]
path = (path asNSString).appendingPathComponent(dbname)
print(path)
//创建队列
queue =FMDatabaseQueue(path: path)
//打开数据库,创建表格
createTable()
//注册通知,清除缓存
NotificationCenter.default.addObserver(self, selector: #selector(clearFZSQLCache), name:NSNotification.Name.UIApplicationDidEnterBackground, object:nil)
}
@objc private func clearFZSQLCache() {
let dateStr =dateString(interval: MAXDBCACHETIME)
let sql ="DELETE FROM T_Status WHERE createTime < ?;"
queue.inDatabase { (db)in
if db?.executeUpdate(sql, withArgumentsIn: [dateStr]) ==true {
print("删除了\(String(describing: db?.changes()))")
}
}
}
func dateString(interval:TimeInterval) -> String {
let date =Date(timeIntervalSinceNow: interval)
dateFormatter.dateFormat ="yyyy-MM-dd HH:mm:ss"
let dateStr =dateFormatter.string(from: date)
print("\(date)----\(dateStr)")
return dateStr
}
}
//MARK: 操作数据
extension FZSQLLiteManager {
//MARK: 更新/插入数据
/*
INSERT OR REPLACE... -->这是数据库特有的语句:主键是新的就插入,一样的会覆盖更新
*/
func updateData(userId:String,dataArr: [[NSString:AnyObject]]) {
//1.准备 SQL
let sql ="INSERT OR REPLACE INTO T_Status (statusId, userId, status) VALUES (?, ?, ?);"
//2. 执行 SQL
/*
1. queue.inDatabase -- 单条操作
2. queue.inTransaction(开启事务) --批量操作
*/
queue.inTransaction { (db, rollback)in
//遍历数组,插入数据
for dicin dataArr {
guardlet statusId = dic["statusId"]as? String,
let jsonData =try? JSONSerialization.data(withJSONObject: dic, options: [])
else{
continue
}
//执行
if db?.executeUpdate(sql, withArgumentsIn: [statusId,userId,jsonData]) ==true
{
print("操作成功")
}else{
print("操作失败")
//回滚
rollback?.pointee =true
break
}
}
//s沙盒路径
let dbname ="test.db"
//拼接路径
var path =NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask,true)[0]
path = (path asNSString).appendingPathComponent(dbname)
let data =NSData(contentsOfFile: path)
if data !=nil {
//MARK: 写到电脑方便测试
if (data!as NSData).write(toFile:"/Users/fuzhong/Desktop/test3.db", atomically:true) ==true {
print("ccccc")
}
}
}
}
//MARK: 查询数据结果
func execSqlQueryData(sql:String) -> [[String:AnyObject]] {
var resultArr = [[String:AnyObject]]()
queue.inDatabase { (db)in
guardlet res = db?.executeQuery(sql, withArgumentsIn: [])
else{
return
}
//取数值
while res.next() {
//取列数
let column = res.columnCount()
//遍历
for iin 0..
guardlet attributeName = res.columnName(for: i),
let attributeValue = res.object(forColumnIndex: i)
else{
continue
}
resultArr.append([attributeName: attributeValueas AnyObject])
//print("\(attributeName)---\(attributeValue)")
}
}
}
return resultArr
}
//MARK: 查询数据 --返回指定的条数(分页)
/// 从数据库中查询
///
/// - Parameters:
/// - userId: 当前用户
/// - since_id: 返回比since_id更大的ID
/// - max_id: 返回比max_id更小的ID
/// - Returns: 结果
func loadData(userId:String,since_id: Int, max_id: Int) -> [[String:AnyObject]] {
// 1. 准备SQL
var sql ="SELECT statusId, userId, status FROM T_Status \n"
sql +="WHERE userId = \(userId) \n "
// 上拉/下拉,都是针对同一个 id进行判断
if since_id >0 {
sql +="AND statusId > \(since_id) \n"
} elseif max_id > 0 {
sql +="AND statusId < \(max_id) \n"
}
/*
1. ORDER BY statusId DESC: 根据statusId降序
2. LIMIT 20 : 每次限制最多返回 20条数据
*/
sql +="ORDER BY statusId DESC LIMIT 20;"
print("SQL语句:\(sql)")
//执行返回结果
let array =execSqlQueryData(sql: sql)
var results = [[String:AnyObject]]()
for dictin array {
// 反序列化
guardlet jsonData = dict["status"]as? Data,
let json =try? JSONSerialization.jsonObject(with: jsonData, options: [])as? [String:AnyObject]
else {
continue
}
// 追加到数组
results.append(json ?? [:])
}
return results
}
}
private extensionFZSQLLiteManager {
@objcfunc createTable() -> () {
//创建数据表
/*
CREATE TABLE IF NOT EXISTS "T_Status" (
"statusId" INTEGER NOT NULL,
"userId" INTEGER NOT NULL,
"status" TEXT,
"createTime" TEXT DEFAULT (datetime('now', 'localtime')),
PRIMARY KEY("statusId","userId")
);
*/
//1. sql
guardlet path = Bundle.main.path(forResource:"status.sql", ofType: nil),
let sqlStr =try? String(contentsOfFile: path)
else {
return
}
//2. 执行 sql --内部串行队列同步执行
queue.inDatabase { (db)in
if db?.executeStatements(sqlStr) ==true {
print("创建成功")
}else{
print("创建失败")
}
}
print("over")
}
}