Pageable
目的
"分页,也称为分页,是将文档分成离散页面的过程,这些页面可以是电子页面或打印页面。"
它是服务器/客户端管理大型数据集的常见技术,将这些数据集分成称为页面的块进行分布。在当今,社交媒体客户端应用通过发明“无限滚动”对此进行了改进。
无限滚动允许用户连续加载内容,消除了用户明确操作的需求。应用加载一些初始数据,然后在用户到达可见内容的底部时加载剩余的数据。这些数据是分页的。
基本用法
那么如何使用这个库呢?其实很简单,只需按照以下步骤进行即可...
步骤 0
创建一个简单的 PageInteractor 对象。PageInteractor 在两个泛型类型上操作。
第一个泛型是 TextView/CollectionView 上显示的 Model
类型。
第二个泛型是为在模型数据中找出重复项而使用的唯一项的类型。默认情况下,如果不需要过滤或 Model
中没有唯一可识别的对象,则可以将其指定为 Any
。
let pageInteractor: PageInteractor<Model, Any> = PageInteractor()
步骤 1
现在需要在 ViewDidLoad() 方法中设置 pageInteractor 实例,以获取第一页数据。
func setupPageInteractor() {
// Require to provide instance of TableView/CollectionView
pageInteractor.pageDelegate = self.tableView
// NetworkManager is implementing PageableService protocol
pageInteractor.service = networkManager
pageInteractor.refreshPage()
}
override func viewDidLoad() {
super.viewDidLoad()
setupPageInteractor()
}
步骤 2
TableView 将从 PageInteractor 请求项目数量。
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return pageInteractor.visibleRow()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Fetch a cell of the appropriate type.
if indexPath.row >= pageInteractor.count() {
let loadingCell = tableView.dequeueReusableCell(withIdentifier: "loadingCell", for: indexPath)
return loadingCell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellTypeIdentifier", for: indexPath)
let cellData = pageInteractor.item(for: indexPath.row)
// Configure the cell’s contents.
cell.textLabel!.text = cellData.name
return cell
}
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
pageInteractor.shouldPrefetch(index: indexPath.row)
}
步骤 3
现在最重要的是向 PageInteractor 提供数据。这是通过实现 PagableService
协议来完成的。它包含两个方法。
protocol PagableService: class {
func loadPage<Item: Decodable>(_ page: Int, completion: @escaping (PageInfo<Item>?) -> Void)
func cancelAllRequests()
}
当 PageInteractor 的 refresh 方法被调用,无论是TableView 加载完毕还是通过 UIRefreshControl 拖动时,它会跟踪页面编号,并通过调用 loadPage<Item: Decodable>(_ page: Int, completion: @escaping (PageInfo<Item>?) -> Void)
来请求加载下一页。其中 page
表示要加载的下一页。一旦页面加载完成,需要返回 PageInfo
结构。
struct PageInfo<T> {
var types: [T] // list of item returned from request
var page: Int // current page
var totalPageCount: Int // total page
}
下面将展示是如何实现的。
extension NetworkManager: PagableService {
func loadPage<Item: Decodable>(_ page: Int, completion: @escaping (PageInfo<Item>?) -> Void) {
var info: PageInfo<Item>?
getNextPage(page: page) { (response) in
// paginated response will have page number as well as total page
switch response {
case let .success(result):
// Provide PageInfo Object from the response or nil in case no response
info = PageInfo(types: result.types,
page: result.page,
totalPageCount: result.totalPageCount)
case let .failure(err):
print(err)
}
// Returning PageInfo Object from callback to PageInteractor
completion(info)
}
}
func cancelAllRequests() {
cancelAll()
}
}
高级用法
Pageable 提供了一些额外功能,如
- 可配置要从服务器获取的起始页面索引。
- 在加载列表中的附加项目时过滤重复项。
If server has added new entry in previous page displayed in pagination,
it results in repeat of last item in fetched new page.
Displayed __1__ On Server
____________ ____2_____
| __1__ | | __3__ | 1
| __2__ | | __4__ | 2
| __3__ | +__10__ == | __4__ | 10
|____4_____| |____5_____| 3
__5__ __6__
__6__ __7__
__7__ __8__ new fetch
__8__ __9__
如果需要过滤重复条目,则需要模型数据的唯一条目密钥路径。这可以在初始化器中设置或在之后设置。
let pageInteractor: PageInteractor<UserModel, Int> = PageInteractor(firstPage: 1, service: networkManager, keyPath: \UserModel.id)
示例
要运行示例项目,请首先克隆仓库,然后从 Example 目录中运行 pod install
。
需求
安装
Pageable 可以通过 CocoaPods 获取。要安装它,只需将以下行添加到您的 Podfile 文件中:
pod 'Pageable'
作者
mrigankgupta, [email protected]
许可协议
Pageable 在 MIT 许可协议下提供。更多详情请查阅 LICENSE 文件。