rx-swift - RxDataSources headerView 和 footerView
问题描述
问题:在从网络服务检索结果之前,CollectionView 页眉和页脚不显示。它们在从服务中检索到项目后显示。
我想要的结果::在从 api 调用检索项目之前显示 CollectionView 页眉和页脚
我尝试过的: 在初始 viewDidLoad 上使用带有页眉和页脚的不同数据源,并在加载结果时将该数据源设置为 nil。没用
我的(不是那么优雅)解决方案: 在 viewDidLoad 上添加 headerView 和 footerView 子视图,并在结果来自服务时将它们替换为 collectionView。
itemsLoading.drive(onNext: { loading in
if loading {
view.addSubview(headerView)
view.addSubview(footerView)
} else {
headerView.removeFromSuperview()
footerView.removeFromSuperView()
view.addSubview(collectionView)
这个问题有更优雅的解决方案吗?
我的代码:只留下与 Rxswift/RxDataSources 相关的部分
struct Input {
let id: Driver<String>
}
struct Output {
let items: Driver<[Item]>
}
class ViewModel {
func transform(input: Input) -> Output {
let items = networkService.getItems(id: input.id) // async operation
return Output(items: items)
}
}
class ViewController: UIViewController {
private let viewModel = ViewModel()
private let disposeBag = DisposeBag()
private let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
override func viewDidLoad() {
super.viewDidLoad()
bindViewModel()
}
private func bindViewModel() {
let dataSource = ViewController.dataSource()
let id = .just(id)
let input = Input(id: id)
let output = viewModel.transform(input: input)
output.items.map { items in
items.map { item in
SectionModel(model: "first Section", items: [item])
}
}
.drive(collectionView.rx.items(dataSource: dataSource))
.disposed(by: disposeBag)
}
extension ViewController {
typealias DataSource = RxCollectionViewSectionedReloadDataSource
static func dataSource() -> DataSource<SectionModel<String, Item>> {
.init(
configureCell: { _, collectionView, indexPath, _ in
let cell = collectionView.dequeueReusableCell(ofType: UICollectionViewCell.self, for: indexPath)
return cell
},
configureSupplementaryView: { _, collectionView, kind, indexPath in
switch kind {
case UICollectionView.elementKindSectionHeader:
let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, kindType: SectionHeader.self, for: indexPath)
return header
case UICollectionView.elementKindSectionFooter:
let footer = collectionView.dequeueReusableSupplementaryView(ofKind: kind, kindType: SectionFooter.self, for: indexPath)
return footer
default:
assert(false, "Unexpected element kind")
}
})
}
}
解决方案
简单的解决方案,我觉得更优雅,是用来startWith
发出一个SectionModel
s 数组,每个都有 0 个项目,但model
包含正确的值。
推荐阅读
- typo3 - 在 Typo3 中为 Mask-Elements 设置后端标题
- elixir - 迁移数据库约束
- python - 在循环网络上使用预训练的句子嵌入
- symfony - 教义 find() 和 querybuilder() 在 PHPUnit 测试中返回不同的结果
- android-studio - Flutter build.gradle 麻烦
- jdbc - 无法使用 Java JDBC 从 AWS EMR 上的 Presto 连接/查询
- javascript - 已声明标识符 - 已声明标识符“userScore”
- javascript - 在 req.user.save() 后表示不保存
- css - 是否可以使表格的前两列与其内容一样宽,而第三列占据剩余空间?
- java - 将我的文件复制到目录中的问题