请求参数说明:(新浪微博为例)
since_id 若指定此参数,则返回ID比since_id大的微博(即比since_id时间晚的微博),默认为0。
max_id 若指定此参数,则返回ID小于或等于max_id的微博,默认为0。
如果 下拉刷新 MaxId = 0 代表我要拿时间最新的微博
如果 上啦加载更多 SinceId = 0 代表我要拿时间更早的微博
封装网络请求方法时,加上since_id和max_id两个参数
内部拼接请求参数
func loadPublicStatusInfo(since_id: Int64 , max_id: Int64 , success: (response: AnyObject?)->(), failure: (error: NSError)->() ) -> Void
1、将tableView的footView赋值为一个UIActivityIndicatorView
2、上拉刷新操作时,监听当前显示的Cell,如果当前显示的是最后一个Cell,并且UIActivityIndicatorView的动画未开启状态时:
- 开启UIActivityIndicatorView的动画,并以isAnimating()值作为参数传入请求数据的方法内(开始请求数据时,停止动画)
- 通过UIActivityIndicatorView的isAnimating()值判断当前是上拉加载更多操作,还是下拉刷新操作的标识
- 通过since_id和max_id这两个参数决定微博数据
- 请求数据完成后,根据上拉\下拉,判断数据的排序问题
每一条微博都有唯一的标识:id--升序,id值越大,发布时间越接近当前时间,id值越小,发布的时间越早
显示数据时,界面越往上,数组角标越小,数据越新,id越大;反之越往下,微博的发布时间越早,id越小
所以请求新数据后的数据排序为
上拉加载更多时: 原始数据(前) + 新数据(后)
下拉刷新数据时: 新数据(前) + 原始数据(后)
示例代码:
import UIKit
private let cellReusedId = "cellReusedId"
class JSHomeTableViewController: JSVistorTableViewController {
//数据容器 (因为后面使用数组参与了运算,可选项不能直接参与运算,需要解包,避免使用麻烦,所以直接初始化了一个空数组)
private var statusArr: [JSStatusModel] = [JSStatusModel]()
////下拉刷新
private let refresh: UIRefreshControl = UIRefreshControl()
//刷新动画View
private lazy var activityView: UIActivityIndicatorView = {
let activity = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.Gray)
activity.backgroundColor = UIColor.whiteColor()
activity.frame = CGRectMake(0, 0, 0, 40)
return activity
}()
override func viewDidLoad() {
super.viewDidLoad()
if !isLogin {
//设置VistorView(未登录)
vistorView?.setupVistorViewInfo(nil, title: nil)
return
}
//首次请求数据
loadStatusData(activityView.isAnimating())
//设置tableView相关信息
setupTableViewInfo()
}
//请求数据 pullUp为true 代表上拉加载更多
private func loadStatusData (pullUp: Bool) -> () {
/*
请求参数说明:
since_id 若指定此参数,则返回ID比since_id大的微博(即比since_id时间晚的微博),默认为0。
max_id 若指定此参数,则返回ID小于或等于max_id的微博,默认为0。
如果 下拉刷新 MaxId = 0 代表我要拿时间最新的微博
如果 上啦加载更多 SinceId = 0 代表我要拿时间更早的微博
*/
//请求完数据,停止activityView的动画下拉刷新(不论请求是否成功)
activityView.stopAnimating()
self.refresh.endRefreshing()
// 让 since_id 和 max_id 默认为0 (默认均为0时,首次请求数组长度为0,服务器会默认提供20条数据,对第一次请求没有影响)
var since_id: Int64 = 0
var max_id: Int64 = 0
if pullUp {
//上拉加载更多
max_id = statusArr.last?.id ?? 0
if max_id > 0 {
//返回ID小于或等于max_id的微博,防止重复,所以减 1
max_id -= 1
}
} else {
//下拉刷新
since_id = statusArr.first?.id ?? 0
}
// 请求数据
JSNetworkTool.sharedNetworkTool.loadPublicStatusInfo(since_id, max_id: max_id, success: { (response) in
guard let res = response?["statuses"] as? [[String: AnyObject]] else {
return
}
var tempArr: [JSStatusModel] = [JSStatusModel]()
for dict in res {
let statusModel = JSStatusModel(dict: dict);
tempArr.append(statusModel)
}
//赋值并刷新数据
//self.statusArr = tempArr
if pullUp {
//上拉加载更多 因为数组参与了运算,可选项不能直接参与运算,需要解包,避免使用麻烦,所以直接初始化了一个空数组
self.statusArr = self.statusArr + tempArr
} else {
//下拉刷新
self.statusArr = tempArr + self.statusArr
}
//刷新数据
self.tableView.reloadData()
}) { (error) in
print("请求出错\(error)")
}
}
//tableView相关信息设置
private func setupTableViewInfo() {
tableView.separatorStyle = .None
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 200
tableView.registerClass(JSHomeStatusTableViewCell.self, forCellReuseIdentifier: cellReusedId)
// 设置footerView
tableView.tableFooterView = activityView
//下拉刷新
refresh.addTarget(self, action: #selector(refreshAction), forControlEvents: UIControlEvents.ValueChanged)
//类似于通知,发送了一个ValueChanged的通知,监测当UIRefreshControl动画转满一周时,执行 #selector(refreshAction)方法
// refresh.sendActionsForControlEvents(UIControlEvents.ValueChanged)
// 添加控件
tableView.addSubview(refresh)
}
//监听 下拉刷新事件
@objc private func refreshAction () -> () {
// 下拉刷新 请求数据
loadStatusData(activityView.isAnimating())
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
数据源方法
extension JSHomeTableViewController {
// MARK: - Table view data source
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return statusArr.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(cellReusedId, forIndexPath: indexPath) as! JSHomeStatusTableViewCell
cell.statusModel = statusArr[indexPath.row]
return cell
}
}
监听当前显示Cell
extension JSHomeTableViewController {
//将要显示Cell
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
//数组长度-1就是当前最后一条数据 而且 activityView没有开启动画 才申请数据
if statusArr.count == indexPath.row + 1 && !activityView.isAnimating() {
//开启动画
activityView.startAnimating()
//请求数据
loadStatusData(activityView.isAnimating())
}
}
}