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

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

转载于:https://juejin.im/post/5b1622a651882513756f09af

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值