注:只有分页显示时才有必要使用footerView的刷新
如果后台的接口返回的数据是分页的话,就需要进行上拉加载的显示,数据确实很少,就没有必要
以下是Swift写的版本
本地缓存的采用的是数据库的方式,采用FMDB框架,并且进行了上面的封装,用来降低耦合性
1.我创建了Manager的管理类,提供单例的获取,创建表以及数据库的查询方法
import UIKit
// 数据库名称
private let dbName = "status.db"
class SQLManager{
// 全局访问点
static let sharedTools:SQLManager = SQLManager()
// 队列方式
let queue:FMDatabaseQueue
// 构造函数
private init(){
// 打开数据库
let path = (NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true).last! as NSString).stringByAppendingPathComponent(dbName)
// 打印路径
print(path)
queue = FMDatabaseQueue(path: path)
// 创建表
createTabel()
}
// 创建表
private func createTabel(){
// 获取文件
let file = NSBundle.mainBundle().pathForResource("db.sql", ofType: nil)!
// 准备sql
let sql = try! String(contentsOfFile: file)
// 执行sql
queue.inDatabase { (db) -> Void in
let resutl = db.executeStatements(sql)
if resutl {
print("创建表成功")
}else {
print("创建表失败")
}
}
}
// 查询本地数据库中的数据 返回一个类型为字典的数组
func execRecord(sql: String) -> [[String: AnyObject]]{
// 创建一个临时可变数组
var tempArray:[[String: AnyObject]] = [[String: AnyObject]]()
// 执行sql
SQLManager.sharedTools.queue.inDatabase { (db) -> Void in
let resultSet = db.executeQuery(sql, withArgumentsInArray: nil)
// 遍历结果
while resultSet.next() {
// 创建一个可变字典
var dict:[String: AnyObject] = [String: AnyObject]()
// for in
for i in 0..<resultSet.columnCount() {
// 类似key
let name = resultSet.columnNameForIndex(i)
// 类似value
let value = resultSet.objectForColumnIndex(i)
// 赋值
dict[name] = value
}
// 保存字典
tempArray.append(dict)
}
}
return tempArray
}
}
2.根据我们要保存的数据,进行相应的类的创建,用来管理模型数据的各种数据库的增删改查的操作
import UIKit
// 清理缓存时间
private let Time: Double = -60*50
class CZStatusDAL: NSObject {
/*
- 为什么缓存微博数据?
- 如果本地有该条微博数据 直接从本地取 为用户节省流量
- 读取缓存数据的过程
- 开启app 请求数据
- 01 检查本地是否有该条数据
- 有 直接使用
- 没有 再网络请求 然后在保存网络下载下来的微博数据
*/
// 检查本地是否有缓存数据
class func checkCache(sinceId:Int64, maxId: Int64, success: SuccessClosure, failure: FailureClosure) {
let result = getCache(sinceId, maxId: maxId)
// 本地有数据从本地取数据
if result?.count > 0 {
print("本地获取")
success(response: result)
}else {
// 本地没有数据 需要到网络请求
CZNetworktools.sharedTools.homeLoadStatusData(sinceId, maxId: maxId, success: { (response) -> () in
// 判断我们请求回来数据是否有值 而且是否是一个数组
guard let res = response?["statuses"] as?[[String: AnyObject]] else {
print("返回数据为nil 或者 类型不匹配")
return
}
print("网络获取")
success(response: res)
// 保存数据
saveCache(res)
}, failure: { (error) -> () in
failure(error: error)
})
}
}
// 查询本地微博数据
class func getCache(sinceId:Int64, maxId: Int64) -> [[String: AnyObject]]?{
// 获取用户uid
guard let userId = CZUserAccountTools.sharedTools.userAccount?.uid else {
print("用户没有登录")
return nil
}
// 准备sql
var sql = "SELECT * FROM T_Status "
sql += "WHERE userid = (userId) "
// 代表下拉刷新
if sinceId > 0{
sql += "AND statusid > (sinceId) "
}
// 上拉加载更多
if maxId > 0 {
sql += "AND statusid <= (maxId) "
}
sql += "ORDER BY statusid DESC "
sql += "LIMIT 20 "
// 执行sql
let result = SQLManager.sharedTools.execRecord(sql)
// 创建一个可变的临时数组
var tempArray:[[String: AnyObject]] = [[String: AnyObject]]()
// 遍历数组
for dic in result {
let data = dic["status"] as! NSData
let dict = try! NSJSONSerialization.JSONObjectWithData(data, options: []) as! [String: AnyObject]
// 保存数据
tempArray.append(dict)
}
return tempArray
}
// 保存网络下载的微博数据
class func saveCache(status: [[String: AnyObject]]) {
// 用户id
guard let userId = CZUserAccountTools.sharedTools.userAccount?.uid else {
print("用户没有登录")
return
}
// 准备sql
// REPLACE 如果上次已经保存微博id 为1234的数据了 然后下次可能重复保存 会造成数据库保存 所以采用 或者替换方式
let sql = "INSERT OR REPLACE INTO T_Status (statusid,status,userid) VALUES (?,?,?)"
// 执行sql
SQLManager.sharedTools.queue.inTransaction { (db, rollback) -> Void in
// 循环
for dic in status {
// 微博id
let statusId = dic["id"] as! NSNumber
// 微博数据
let statusDic = try! NSJSONSerialization.dataWithJSONObject(dic, options: [])
let result = db.executeUpdate(sql, withArgumentsInArray: [statusId,statusDic,userId])
if result {
print("保存数据成功")
}else {
print("保存数据失败")
// 失败回滚
rollback.memory = true
}
}
}
}
// 删除缓存数据
class func deleteCache() {
// 获取当前时间 2016-07-08 10:39:37
let date = NSDate(timeIntervalSinceNow: Time)
//
let df = NSDateFormatter()
// 指定区域
df.locale = NSLocale(localeIdentifier: "en_US")
// 指定格式
df.dateFormat = "yyyy-MM-dd HH:mm:ss"
// 时间字符串
let timeStr = df.stringFromDate(date)
print(timeStr)
// 准备sql
let sql = "DELETE FROM T_Status WHERE createtime < '(timeStr)'"
// 执行sql
SQLManager.sharedTools.queue.inDatabase { (db) -> Void in
let result = db.executeUpdate(sql, withArgumentsInArray: nil)
if result {
print("删除缓存成功")
}else {
print("删除缓存失败")
}
}
}
}
3.创建的表的语句可以单独写在一个文件里面,通过加载Bundle进行获取
CREATE TABLE IF NOT EXISTS "T_Status" (
"statusid" INTEGER NOT NULL,
"status" TEXT,
"userid" INTEGER NOT NULL,
"createtime" TEXT DEFAULT (datetime('now','localtime')),
PRIMARY KEY("statusid","userid")
)
4.
更新数组时,应当对上拉加载和下拉刷新进行判断,对数据元进行相应的操作
// 上拉加载更多
if pullUp{
self.statusArray = self.statusArray + tempArray
}else{
// 下拉刷新
self.statusArray = tempArray + self.statusArray
self.pullDownTipLabelAnim(tempArray.count)
}
// 刷新UI
self.tableView.reloadData()
下面我们展示OC里面相同逻辑的写法
1:
创建管理者
2:模型工具类
感谢大家前来指正!!