InfiniteKit 0.1.2

InfiniteKit 0.1.2

Carl维护。



 
依赖
RxSwift~> 4.3
RxCocoa~> 4.3
RxDataSources~> 3.0
RxSwiftExt~> 3.0
 

logo

Version License Platform

  • 使用声明式方式创建`Infinite Scroll`,代码更少
  • 默认覆盖所有相关的UI状态
  • 完全可定制
  • 使用RxTest进行良好的测试

了解更多内容

在现实世界的iOS应用程序中,大部分从服务器加载的数据都是以`UITableView`和`UICollectionView`显示的。为了创建一个使用服务器数据的完整功能的无限滚动,开发者需要实现许多事情

  • 加载视图:在重新加载或第一次加载时显示
  • 空视图:当服务器返回空数据时显示
  • 错误视图:当发生网络错误时显示
  • 下拉刷新
  • 下拉加载更多

大多数初级开发者会反复构建数据流程,这最终会导致代码冗余和重复的测试用例。
在大多数情况下,无限滚动可以被抽象为一种通用模式。
InfiniteKit的存在就是为了让开发者轻松使用这个模式,快速创建功能完整的无限滚动,并以声明式方式实现。

让我们使用Github Open API创建一个列出github用户的无限滚动

首先,看看InfiniteKit中的抽象:InfiniteList<Cell, DataPack, CellModel>

  • CellUITableViewCell的子类
  • 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 文件。