- 使用声明式方式创建`Infinite Scroll`,代码更少
- 默认覆盖所有相关的UI状态
- 完全可定制
- 使用RxTest进行良好的测试
了解更多内容
在现实世界的iOS应用程序中,大部分从服务器加载的数据都是以`UITableView`和`UICollectionView`显示的。为了创建一个使用服务器数据的完整功能的无限滚动,开发者需要实现许多事情
- 加载视图:在重新加载或第一次加载时显示
- 空视图:当服务器返回空数据时显示
- 错误视图:当发生网络错误时显示
下拉刷新
下拉加载更多
大多数初级开发者会反复构建数据流程,这最终会导致代码冗余和重复的测试用例。
在大多数情况下,无限滚动可以被抽象为一种通用模式。
InfiniteKit的存在就是为了让开发者轻松使用这个模式,快速创建功能完整的无限滚动,并以声明式方式实现。
让我们使用Github Open API创建一个列出github用户的无限滚动
首先,看看InfiniteKit中的抽象:InfiniteList<Cell, DataPack, CellModel>
Cell
是UITableViewCell
的子类DataPack
代表从服务器接收的数据包CellModel
需要从DataPack
中提取出来,并用于渲染单元格
我们声明必要的类型
typealias Cell = UITableViewCell
struct CellModel: Codable {
let id: Int
let login: String
}
typealias DataPack = (data: [CellModel], offset: Int)
typealias List = InfiniteList<Cell, DataPack, CellModel>
接下来,我们声明如何获取数据并使用它们来渲染我们的单元格,只需要使用四个闭包
列表的初始化获取
列表的下一次获取
列表的数据提取器
列表的单元格装饰者
List.InitFetch
是() -> Single<DataPack>
的别名,生成第一次数据获取。
let initFetch: List.InitFetch = {
let url = "https://api.github.com/users"
let req = genReq(url: url)
return sendReq(req, decodeWith: [CellModel].self)
.map { (data: $0, offset: $0.count) }
.asSingle()
}
List.NextFetch
是(DataPack) -> Single<DataPack?>
的别名,基于最后获取的结果生成数据获取,如果没有更多数据返回nil。
let nextFetch: List.NextFetch = { lastDataPack in
let url = "https://api.github.com/users"
let params = ["since": String(lastDataPack.offset)]
let req = genReq(url: url, params: params)
return sendReq(req, decodeWith: [CellModel].self)
.map { (data: $0, offset: lastDataPack.offset + $0.count) }
.asSingle()
}
List.DataExtractor
是([DataPack]) -> [CellModel]
的别名,将数据包映射到单元格模型。
let dataExtractor: List.DataExtractor = { dataPacks in
let flattened = dataPacks.map { $0.data }.flatMap { $0 }
// remove duplicate & order asc by id
return Array(Set(flattened)).sorted(by: { $0.id < $1.id })
}
(Cell, CellModel) -> Void
的别名,使用模型更新单元格。
let cellDecorator: List.CellDecorator = { cell, model in
cell.textLabel?.text = model.login
}
现在我们可以使用这个配置来创建我们的 List
,它是 ViewController
的子类。
let config = List.Config(
initFetch: initFetch,
nextFetch: nextFetch,
dataExtractor: dataExtractor,
cellDecorator: cellDecorator
)
let list = List(config: config)
List
现在具有默认的 加载视图
、空视图
、错误视图
、下拉刷新
、下拉加载更多
,核心数据流程已经由库进行过充分测试。
您可以通过配置 List.Config
来自定义 List
。
config.refreshControl // UIRefreshControl
config.loadingView // UIView
config.emptyViewAndReloadTrigger // (UIView, ControlEvent<()>)
config.errorViewAndReloadTrigger // (UIView, ControlEvent<()>)
待办事项
- InfiniteList
- InfiniteSectionList
- InfiniteCollection
- InfiniteSectionCollection
示例
要运行示例项目,请首先克隆仓库,然后从示例目录运行 pod install
。
要求
安装
InfiniteKit 通过 CocoaPods 提供。要安装它,只需将以下行添加到您的 Podfile 中
pod 'InfiniteKit'
作者
wddwycc, [email protected]
授权协议
InfiniteKit 在 MIT 授权协议下可用。有关更多信息,请参阅 LICENSE 文件。