分页展示以及下拉刷新的本地保存

注:只有分页显示时才有必要使用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\n"

        sql += "WHERE userid = \(userId)\n"

        // 代表下拉刷新

        if sinceId > 0{

            sql += "AND statusid > \(sinceId)\n"

        }

        // 上拉加载更多

        if maxId > 0 {

            sql += "AND statusid <= \(maxId)\n"

        }

        sql += "ORDER BY statusid DESC\n"

        sql += "LIMIT 20\n"

        

        // 执行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:模型工具类

 

感谢大家前来指正!!

 

posted on 2016-10-13 20:11  敏言慎行  阅读(197)  评论(0编辑  收藏  举报

导航