RxDataSources headerView 和 footerView
RxDataSources headerView and 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
数组,每个数组都有 0 个项目,但 model
包含正确的值。
问题:在从网络服务检索结果之前,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
数组,每个数组都有 0 个项目,但 model
包含正确的值。