UITableView
易用
主要特性 | |
---|---|
跳过 UITableViewDataSource 和 UITableViewDelegate 的样板代码,直接构建您的 UITableView ! |
|
基于闭包的 API 用于部分和行的配置 | |
内置分页功能 | |
单元测试 | |
使用 Swift 4.2 编写 |
OKTableViewLiaison
是
要求
- Xcode 10.0+
- iOS 9.0+
安装
CocoaPods
首选的安装方法是使用 CocoaPods。请将以下内容添加到您的 Podfile
:
pod 'OKTableViewLiaison'
示例
要运行示例项目,请克隆仓库,然后首先从 Example 文件夹中运行 pod install
。
使用
OKTableViewLiaison
允许您更轻松地填充和操作 UITableView
行和部分。
入门
要开始,您只需要将一个 UITableView
实例用 OKTableViewLiaison
进行站席。
let liaison = OKTableViewLiaison()
let tableView = UITableView()
liaison.liaise(tableView: tableView)
通过将您的 tableView 与联动器联接,联动器成为其 UITableViewDataSource
、UITableViewDelegate
和 UITableViewDataSourcePrefetching
。如果您想从联动器中移除 tableView,只需调用 liaison.detach()
。
OKTableViewLiaison 使用两种主要类型填充部分和行
部分
struct OKTableViewSection
要为我们的 tableView 创建一个部分,创建一个 OKTableViewSection
实例并将其添加到联动器中。
let section = OKTableViewSection()
let liaison = OKTableViewLiaison(sections: [section])
或
let section = OKTableViewSection()
liaison.append(section: section)
补充部分视图
要通知联动器您的 OKTableViewSection
将显示标题和/或页脚视图,您必须在初始化期间提供 OKTableViewSectionComponentDisplayOption
实例。
OKTableViewSectionComponentDisplayOption
是一个枚举,它通知联动器为给定部分显示哪些补充视图。标题/页脚视图由以下表示:
class OKTableViewSectionComponent<View: UITableViewHeaderFooterView, Model>
let header = OKTableViewSectionComponent<UITableViewHeaderFooterView, User>(.dylan)
let section = OKTableViewSection(componentDisplayOption: .header(component: header))
您可以使用 CGFloat 值或闭包来设置部分组件的静态高度
header.set(height: .height, 55)
header.set(height: .height) { user -> CGFloat in
return user.username == "dylan" ? 100 : 75
}
header.set(height: .estimatedHeight, 125)
如果在部分组件中没有提供高度,联动器将假设补充视图是自定尺寸,并返回 .height
为 UITableView.automaticDimension
。请确保提供 .estimatedHeight
以避免布局问题。
您可以使用 func set(command: OKTableViewSectionComponentCommand, with closure: @escaping (View, Model, Int) -> Void)
在所有以下生命周期事件中自定义 OKTableViewSectionComponent
视图
- 配置
- didEndDisplaying
- willDisplay
header.set(command: .configuration) { view, user, section in
view.textLabel?.text = user.username
}
header.set(command: .willDisplay) { view, user, section in
print("Header: \(view) will display for Section: \(section) with User: \(user)")
}
行
class OKTableViewRow
要为某个部分添加行,请创建一个OKTableViewRow
实例并将其传递给OKTableViewSection
的初始化器,或者如果行是在实例化后添加的,可以通过联盟完成此操作。
let row = OKTableViewRow<RowTableViewCell, RowModel>(model: RowModel(type: .small))
let section = OKTableViewSection(rows: [row])
liaison.append(section: section)
或
let row = OKTableViewRow<RowTableViewCell, RowModel>(model: RowModel(type: .small))
let section = OKTableViewSection()
liaison.append(section: section)
liaison.append(row: row)
OKTableViewRow
的高度配置与OKTableViewSection
类似。
row.set(height: .height, 300)
row.set(height: .estimatedHeight, 210)
row.set(height: .height) { model -> CGFloat in
switch model.type {
case .large:
return 400
case .medium:
return 200
case .small:
return 50
}
}
如果未提供高度,联盟将假设单元格是自定大小的,并返回UITableView.automaticDimension
。
OKTableViewRow
可以通过使用func set(command: OKTableViewRowCommand, with closure: @escaping (Cell, Model, IndexPath) -> Void)
在以下所有生命周期事件中进行自定义:
- accessoryButtonTapped
- 配置
- 删除
- 取消选择
- didEndDisplaying
- 结束编辑
- 高亮
- 选择
- 取消高亮
- 插入
- 移动
- 刷新
- 开始编辑
- 将要取消选择
- willDisplay
- 将要选择
row.set(command: .configuration) { cell, model, indexPath in
cell.label.text = model.text
cell.label.font = .systemFont(ofSize: 13)
cell.contentView.backgroundColor = .blue
cell.selectionStyle = .none
}
row.set(command: .didSelect) { cell, model, indexPath in
print("Cell: \(cell) selected at IndexPath: \(indexPath)")
}
OKTableViewRow
还可以通过使用func set(prefetchCommand: OKTableViewPrefetchCommand, with closure: @escaping (Model, IndexPath) -> Void)
利用UITableViewDataSourcePrefetching
。
row.set(prefetchCommand: .prefetch) { model, indexPath in
model.downloadImage()
}
row.set(prefetchCommand: .cancel) { model, indexPath in
model.cancelImageDownload()
}
单元格/视图注册
OKTableViewLiaison
代表你处理UITableView
视图的复用,利用你的部分/行OKTableViewRegistrationType<T>
。
OKTableViewRegistrationType
告诉联盟是否应该通过Nib
或Class
注册可重用视图。
默认情况下,OKTableViewRow
使用OKTableViewRegistrationType<Cell>.defaultClassType
实例化。
OKTableViewSection
的补充视图注册封装在OKTableViewSectionComponentDisplayOption
中。默认情况下,OKTableViewSection
的componentDisplayOption
使用.none
实例化。
分页
OKTableViewLiaison
具有处理分页需求的功能。要配置分页的联盟,只需将其paginationDelegate
设置为OKTableViewLiaisonPaginationDelegate
的实例。
OKTableViewLiaisonPaginationDelegate
声明了三个方法
func isPaginationEnabled() -> Bool
,通知联盟是否应该在用户滚动过最后一个单元格时显示分页旋转器。
func paginationStarted(indexPath: IndexPath)
,传递联盟管理的最后OKTableViewRow
的索引路径。
func paginationEnded(indexPath: IndexPath)
,传递联盟附加的每个新OKTableViewRow
的第一个索引路径。
要更新分页期间的联系结果,只需使用 append(sections: [OKAnyTableViewSection])
或 func append(rows: [OKAnyTableViewRow])
,联系人将自动处理删除分页加载指示器。
要使用自定义的分页加载指示器,您可以在 OKTableViewLiaison
的初始化过程中传递一个 OKAnyTableViewRow
实例。默认情况下,它使用框架提供的 OKPaginationTableViewRow
。
技巧与窍门
因为 OKTableViewSection
和 OKTableViewRow
使用泛型并管理视图/单元格类型的注册,实例化多个不同的部分和行配置可能会变得冗长。创建子类或使用工厂创建各种 OKTableViewRow
/OKTableViewSectionComponent
类型可能很有用。
final class TextTableViewRow: OKTableViewRow<PostTextTableViewCell, String> {
init(text: String) {
super.init(text,
registrationType: .defaultNibType)
}
}
static func imageRow(with image: UIImage) -> AnyTableViewRow {
let row = OKTableViewRow<ImageTableViewCell, UIImage>(image)
row.set(height: .height, 225)
row.set(command: .configuration) { cell, image, indexPath in
cell.contentImageView.image = image
cell.contentImageView.contentMode = .scaleAspectFill
}
return row
}
贡献
OKTableViewLiaison
同时是框架也在发展初期。它的实现还不完美。并非所有 UITableView
功能都已经实现。如果您想帮助将 OKTableViewLiaison
带到更好的地方,欢迎提交 pull request。
作者
许可证
OKTableViewLiaison 是在 MIT 许可证下可用的。有关更多信息,请参阅 LICENSE 文件。