RxSwift重载动画中的RxDatasource don';更新数据源
RxSwift[RxTableViewSectionedAnimatedDataSource]重新加载动画中的RxDatasource不更新数据源。我犯了什么错误?我甚至无法将我的动作与按钮正确绑定 TableDataSource和表编辑命令RxSwift重载动画中的RxDatasource don';更新数据源,swift,uitableview,rx-swift,rxdatasources,Swift,Uitableview,Rx Swift,Rxdatasources,RxSwift[RxTableViewSectionedAnimatedDataSource]重新加载动画中的RxDatasource不更新数据源。我犯了什么错误?我甚至无法将我的动作与按钮正确绑定 TableDataSource和表编辑命令 struct TableDataSource { var header: String var items: [Item] var SectionViewModel: SectionViewModel } extension Ta
struct TableDataSource {
var header: String
var items: [Item]
var SectionViewModel: SectionViewModel
}
extension TableDataSource: AnimatableSectionModelType {
var identity: String {
return header
}
type alias Item = Data
init(original: TableDataSource, items: [Item]) {
self = original
self.items = items
self.sectionViewModel = original.sectionViewModel
}
}
enum TableViewEditingCommand {
case deleteSingle(IndexPath)
case clearAll(IndexPath)
case readAll(IndexPath)
}
struct SectionedTableViewState {
var sections: [TableDataSource]
init(sections: [TableDataSource]) {
self.sections = sections
}
func execute(command: TableViewEditingCommand) -> SectionedTableViewState {
var sections = self.sections
switch command {
// Delete single item from datasource
case .deleteSingle(let indexPath):
var items = sections[indexPath.section].items
items.remove(at: indexPath.row)
if items.count <= 0 {
sections.remove(at: indexPath.section)
} else {
sections[indexPath.section] = TableDataSource(
original: sections[indexPath.section],
items: items) }
// Clear all item from datasource with isUnread = false
case .clearAll(let indexPath):
sections.remove(at: indexPath.section)
// Mark all item as read in datasource with isUnread = true
case .readAll(let indexPath):
var items = sections[indexPath.section].items
items = items.map { var unread = $0
if $0.isUnRead == true { unreadData.isUnRead = false }
return unreadData
}
sections.remove(at: indexPath.section)
if sections.count > 0 {
let allReadItems = sections[indexPath.section].items + items
sections[indexPath.section] = TableDataSource(
original: sections[indexPath.section],
items: allReadItems)
}
}
return SectionedTableViewState(sections: sections)
}
}
struct TableDataSource{
变量头:字符串
可变项目:[项目]
var SectionViewModel:SectionViewModel
}
扩展表数据源:AnimatableSectionModelType{
变量标识:字符串{
回流集管
}
类型别名项=数据
初始化(原始:TableDataSource,项:[Item]){
自我=原创
self.items=项目
self.sectionViewModel=原始的.sectionViewModel
}
}
枚举表视图编辑命令{
大小写deleteSingle(IndexPath)
大小写clearAll(IndexPath)
case readAll(indexath)
}
结构SectionTableViewState{
变量部分:[TableDataSource]
初始化(节:[TableDataSource]){
self.sections=节
}
func execute(命令:TableViewEditingCommand)->SectionedTableViewState{
var截面=自截面
开关命令{
//从数据源中删除单个项
case.deletesSingle(让indexPath):
var items=sections[indexPath.section].items
items.remove(位于:indexPath.row)
如果项目数为0.0{
让allReadItems=sections[indexPath.section].items+items
sections[indexPath.section]=TableDataSource(
原文:第[indexPath.section]节,
项目:所有阅读项目)
}
}
返回SectionedTableViewState(节:节)
}
}
这是我的控制器及其扩展
class ViewController: UIViewController, Storyboardable {
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var closeButton: UIButton!
@IBOutlet weak var titleText: UILabel!
var viewModel: ViewModel!
let disposeBag = DisposeBag()
let sectionHeight: CGFloat = 70
let dataSource = ViewController.dataSource()
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
bindInitials()
bindDataSource()
bindDelete()
}
private func bindInitials() {
tableView.delegate = nil
tableView.rx.setDelegate(self)
.disposed(by: disposeBag)
registerNibs()
}
private func registerNibs() {
let headerNib = UINib.init(
nibName: TableViewSection.identifier,
bundle: nil)
tableView.register(
headerNib,
forHeaderFooterViewReuseIdentifier: TableViewSection.identifier)
}
}
extension ViewController: Bindable {
func bindViewModel() {
bindActions()
}
private func bindDataSource() {
bindDelete()
// tableView.dataSource = nil
// Observable.just(sections)
// .bind(to: tableView.rx.items(dataSource: dataSource))
// .disposed(by: disposeBag)
}
private func bindDelete() {
/// TODO: to check and update delete code to work properly to sink with clear all and mark all as read
guard let sections = self.viewModel?.getSections() else {
return
}
let deleteState = SectionedTableViewState(sections: sections)
let deleteCommand = tableView.rx.itemDeleted.asObservable()
.map(TableViewEditingCommand.deleteSingle)
tableView.dataSource = nil
Observable.of(deleteCommand)
.merge()
.scan(deleteState) {
(state: SectionedTableViewState,
command: TableViewEditingCommand) -> SectionedTableViewState in
return state.execute(command: command) }
.startWith(deleteState) .map { $0.sections }
.bind(to: tableView.rx.items(dataSource: dataSource))
.disposed(by: disposeBag)
}
private func bindActions() {
guard let openDetailsObserver = self.viewModel?.input.openDetailsObserver,
let closeObserver = self.viewModel?.input.closeObserver else {
return
}
viewModel.output.titleTextDriver
.drive(titleText.rx.text)
.disposed(by: disposeBag)
// viewModel.input.dataSourceObserver
// .mapObserver({ (result) -> [Data] in
// return result
// })
// .disposed(by: disposeBag)
/// Close button binding with closeObserver
closeButton.rx.tap
.bind(to: (closeObserver))
.disposed(by: disposeBag)
/// Tableview item selected binding with openDetailsObserver
tableView.rx.itemSelected
.map { indexPath in
return (self.dataSource[indexPath.section].items[indexPath.row])
}.subscribe(openDetailsObserver).disposed(by: disposeBag)
}
}
extension ViewController: UITableViewDelegate {
static func dataSource() -> RxTableViewSectionedAnimatedDataSource<TableDataSource> {
return RxTableViewSectionedAnimatedDataSource(
animationConfiguration: AnimationConfiguration(insertAnimation: .fade,
reloadAnimation: .fade,
deleteAnimation: .fade),
configureCell: { (dataSource, table, idxPath, item) in
var cell = table.dequeueReusableCell(withIdentifier: TableViewCell.identifier) as? TableViewCell
let cellViewModel = TableCellViewModel(withItem: item)
cell?.setViewModel(to: cellViewModel)
return cell ?? UITableViewCell()
}, canEditRowAtIndexPath: { _, _ in return true })
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
guard var headerView = tableView.dequeueReusableHeaderFooterView(
withIdentifier: TableViewSection.identifier)
as? TableViewSection
else { return UITableViewHeaderFooterView() }
let viewModel = self.dataSource[section].sectionViewModel
headerView.setViewModel(to: viewModel)
headerView.dividerLine.isHidden = section == 0 ? true : false
headerView.section = section
let data = TableViewEditingCommand.clearAll(IndexPath(row: 0, section: section ?? 0))
// /// Section button binding with closeObserver
// headerView.sectionButton.rx.tap
// .map(verseNum -> TableViewEditingCommand in (TableViewEditingCommand.deleteSingle))
// .disposed(by: disposeBag)
headerView.sectionButtonTappedClosure = { [weak self] (section, buttonType) in
if buttonType == ButtonType.clearAll {
self?.showClearAllConfirmationAlert(section: section, buttonType: buttonType)
} else {
self?.editAction(section: section, buttonType: buttonType)
}
}
return headerView
}
func editAction(section: Int, buttonType: ButtonType) {
var sections = self.dataSource.sectionModels
let updateSection = (sections.count == 1 ? 0 : section)
switch buttonType {
/// Clear all
case .clearAll:
sections.remove(at: updateSection)
let data = SectionedTableViewState(sections: sections)
self.tableView.dataSource = nil
Observable.of(data)
.startWith(data) .map { $0.sections }
.bind(to: tableView.rx.items(dataSource: dataSource))
.disposed(by: disposeBag)
/// Mark all as read
case .markAllAsRead:
if updateSection == 0 { sections = self.viewModel.getSections() }
var items = sections[updateSection].items
items = items.map { var unread = $0
if $0.isUnRead == true { unread.isUnRead = false }
return unread
}
sections.remove(at: updateSection)
let allReadItems = sections[updateSection].items + items
sections[updateSection] = TableDataSource(
original: sections[updateSection],
items: allReadItems)
let data = SectionedTableViewState(sections: sections)
self.tableView.dataSource = nil
Observable.of(data)
.startWith(data) .map { $0.sections }
.bind(to: tableView.rx.items(dataSource: dataSource))
.disposed(by: disposeBag)
}
}
func showClearAllConfirmationAlert(section: Int, buttonType: ButtonType) {
let alert = UIAlertController(title: "Clear All",
message: "Are you sure, you want to clear all Items?",
preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { action in
switch action.style{
case .default:
self.editAction(section: section, buttonType: buttonType)
case .cancel: break
case .destructive: break
default:break
}}))
let cancel = UIAlertAction(title: "Cancel", style: .default, handler: { action in
})
alert.addAction(cancel)
self.present(alert, animated: true, completion: nil)
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return sectionHeight
}
}
类ViewController:UIViewController,可故事板{
@IBVAR表格视图:UITableView!
@IB出口弱var关闭按钮:UIButton!
@IBVAR标题文本:UILabel!
var viewModel:viewModel!
设disposeBag=disposeBag()
让截面高度:CGFloat=70
让dataSource=ViewController.dataSource()
重写func viewDidLoad(){
super.viewDidLoad()
}
覆盖函数视图将出现(uo动画:Bool){
超级。视图将显示(动画)
bindInitials()
bindDataSource()
bindDelete()
}
private func bindInitials(){
tableView.delegate=nil
tableView.rx.setDelegate(自身)
.处置(由:处置人)
registerNibs()
}
专用函数注册表项{
让headerNib=UINib.init(
nibName:TableViewSection.identifier,
捆绑:无)
tableView.register(
校长,
forHeaderFooterViewReuseIdentifier:TableViewSection.identifier)
}
}
扩展视图控制器:可绑定{
func bindViewModel(){
bindActions()
}
私有func bindDataSource(){
bindDelete()
//tableView.dataSource=nil
//可观察。仅(部分)
//.bind(到:tableView.rx.items(数据源:数据源))
//.处置(由:处置人)
}
私有函数bindDelete(){
///TODO:检查并更新删除代码以正常工作,使用“全部清除”并将所有标记为已读
guard let sections=self.viewModel?.getSections()else{
返回
}
让deleteState=SectionedTableViewState(节:节)
让deleteCommand=tableView.rx.itemDeleted.asObservable()
.map(TableViewEditingCommand.deleteSingle)
tableView.dataSource=nil
可观察的(删除命令)
.merge()
.scan(删除状态){
(状态:SectionedTableViewState,
命令:TableViewEditingCommand)->中的SectionedTableViewState
返回状态.execute(command:command)}
.startWith(deleteState).map{$0.0}
.bind(到:tableView.rx.items(数据源:数据源))
.处置(由:处置人)
}
私有函数bindActions(){
让openDetailsObserver=self.viewModel?.input.openDetailsObserver,
让closeObserver=self.viewModel?.input.closeObserver-else{
返回
}
viewModel.output.titleTextDriver
.drive(titleText.rx.text)
.处置(由:处置人)
//viewModel.input.dataSourceObserver
//.mapObserver({(结果)->[数据]位于
//返回结果
// })
//.处置(由:处置人)
///使用closeObserver关闭按钮绑定
closeButton.rx.tap
.绑定(到:(观察者)
.处置(由:处置人)
///使用openDetailsObserver绑定选定的Tableview项
tableView.rx.itemSelected
.map{indexPath in
返回(self.dataSource[indexPath.section].items[indexPath.row])
}.subscribe(openDetailsObserver).disposed(由:disposeBag)
}
}
扩展视图控制器:UITableViewDelegate{
静态func dataSource()->rxtableviewsectionedanimatedatasource{
返回RxTableViewSectionedAnimatedDataSource(
animationConfiguration:animationConfiguration(插入动画:.fade,
重新加载动画:。淡入淡出,
删除动画:。淡入淡出),
configureCell:{(数据源、表、idxPath、项)位于
var cell=table.dequeueReusableCell(标识符为TableViewCell.identifier)作为TableViewCell
让cellViewModel=TableCellViewModel(withItem:item)
cell?.setViewModel(至:cellViewModel)
返回单元格??UITableViewCell()
},CaneditRowatineXpath:{{uu,{uu返回true})
}
func tableView(tableView:UITableView,viewForHeaderInSection:Int)->UIView{
class ViewModel {
private enum Constants {
static let titleText = "Test".localized
static let testHistoryHeaderText = "test".localized
static let unreadHeaderText = "Unread".localized
}
struct Input {
let dataSourceObserver: AnyObserver<[Data]>
let openDetailsObserver: AnyObserver<Data>
let closeObserver: AnyObserver<Void>
let sectionButtonTappedObserver: AnyObserver<IndexPath>
}
struct Output {
let titleTextDriver: Driver<String>
let dataSourceDriver: Driver<[Data]>
let viewComplete: Observable<DataCoordinator.Event>
}
let input: Input
let output: Output
private let dataSourceSubject = PublishSubject<[Data]>()
private let closeSubject = PublishSubject<Void>()
private let openDetailsSubject = BehaviorSubject<Data>(value:Data())
private let sectionButtonTappedSubject = PublishSubject<IndexPath>()
private let disposeBag = DisposeBag()
init(withRepository repository: Repository) {
input = Input(
dataSourceObserver: dataSourceSubject.asObserver(),
openDetailsObserver: openDetailsSubject.asObserver(),
closeObserver: closeSubject.asObserver(), sectionButtonTappedObserver: sectionButtonTappedSubject.asObserver()
)
let closeEventObservable = closeSubject.asObservable().map { _ in
return Coordinator.Event.goBack
}
let openDetailsEventObservable = openDetailsSubject.asObservable().map { _ in
return Coordinator.Event.goToDetails
}
let viewCompleteObservable = Observable.merge(closeEventObservable, openDetailsEventObservable)
let list = ViewModel.getData(repository: repository)
output = Output(
titleTextDriver: Observable.just(Constants.titleText).asDriver(onErrorJustReturn: Constants.titleText),
dataSourceDriver: Observable.just(list).asDriver(onErrorJustReturn: list),
viewComplete: viewCompleteObservable)
}
///TODO: To be updated as per response after API integration
static func getData(repository: Repository) -> [Data] {
return repository.getData()
}
func getSections() -> [TableDataSource] {
let List = ViewModel.getData(repository: Repository())
let unread = list.filter { $0.isUnRead == true }
let read = list.filter { $0.isUnRead == false }
let headerText = String(format:Constants.unreadHeaderText, unread.count)
let sections = [TableDataSource(
header: headerText,
items: unread,
sectionViewModel: SectionViewModel(
withHeader: headerText,
buttonType: ButtonType.markAllAsRead.rawValue,
items: unread)),
TableDataSource(
header: Constants.historyHeaderText,
items: read,
SectionViewModel: SectionViewModel(
withHeader: Constants.historyHeaderText,
buttonType: ButtonType.clearAll.rawValue,
items: read))]
return sections
}
}