TableView
分頁載入是我們在開發中最常遇到的一種需求,裡面的邏輯並不複雜,但如何把他們寫好,程式碼能夠儘量多的複用起來就得下一點功夫了。
在 Objective-C
中我們可能會通過繼承來抽象分頁的邏輯,但是從程式碼工程上是能不用繼承就儘量不要使用。在 swfit
中我們可以利用 protocol
來很好的抽象這部分邏輯。
首先我們需要定義分頁的幾個常用的屬性,可用程式碼描述如下:
protocol PullToRefreshable: DataSourceType {
/// tableView 所用到的資料來源
var datas: Pages<Item>? { get set }
/// 重新整理的 view 可以是: UIScrollView/UITableView/UICollctionView
var refreshView: UIScrollView { get }
/// 請求 `target`: TargetType 同時封裝了 `url`, `parameters`, `method`
var refreshTarget: TargetType { get }
func refresh()
func loadMore()
/// 在此方法中呼叫 tableView.reloadData()
func reloadData()
}
複製程式碼
利用 Extension
我們可以預設實現請求網路的方法
extension PullToRefreshable {
func refresh() {
Network.default.request(target: refreshTarget) {[weak self] (result) in
self?.refreshView.mj_header.endRefreshing()
switch result {
case let .success(response):
// Added JSON Parser
self?.reloadData()
case .error(_, _):
break
}
}
}
}
複製程式碼
類似的其他方法都可以新增預設實現。
最後我們如果哪個 tableView
需要實現分頁,我們只要去 conform 這個 protocol
即可。程式碼大概長這樣:
extension MessageDetailViewController: PullToRefreshable {
typealias Item = MessageDetail
var refreshView: UIScrollView {
return tableView
}
var refreshTarget: TargetType {
return UserTarget.messgaeDetail(account_no: accountNo, page: 1)
}
func reloadData() {
tableView.reloadData()
}
}
複製程式碼
是不是簡單了很多呢?
在這裡很多同學會不明白分頁最重要的 page
引數去哪裡了呢?我們可以回到上面看下是不是有個 Pages
物件,在這裡我們封裝了分頁相關的屬性,在 loadMore 方法中請求的時候只要將引數 page
賦值成 nextPage
即可。
struct Pages<T: Mappable>: Mappable {
var currentPage: Int = 1
var pageSize: Int = 20
var totalPage: Int = 0
var totalRecords: Int = 0
var items: [T] = [T]()
var nextPage: Int {
return currentPage + 1
}
init?(map: Map) {}
mutating func mapping(map: Map) {
items <- map["items"]
currentPage <- map["current_page"]
pageSize <- map["page_size"]
totalPage <- map["total_page"]
totalRecords <- map["total_records"]
}
}
複製程式碼
這裡暫時提供了一種思路,部分程式碼已被省略,如果有其他更好的方式,希望多多交流。