阅读 867

iOS 中使用 protocol 来重构分页加载

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"]
    }
}
复制代码

这里暂时提供了一种思路,部分代码已被省略,如果有其他更好的方式,希望多多交流。

文章分类
iOS
文章标签