我怎样才能知道 table 视图是否被选为 Observable<Bool>?
How can I get whether a table view is selected as an Observable<Bool>?
在我的应用程序中,我有一个包含大量行的 table 视图。 table 视图由一个可观察对象填充。我正在使用 RxTableViewSectionedAnimatedDataSource
.
使用 RxDataSources 来执行此操作
table 视图的行表示用户可以对其执行操作的某种项目。这意味着我希望某些按钮在行被 selected 时出现,并且我希望这些按钮在没有行被 selected 时消失。这些按钮是用户可以对项目执行的操作。
我想我可以观察 indexPathForSelectedRow
属性 并将其绑定到 button.rx.isHidden
,像这样:
[actionButton1, actionButton2, actionButton3].forEach { (button) in
button?.isHidden = true // they are always hidden initially
self.tableView.rx.observe(IndexPath?.self, "indexPathForSelectedRow")
.map { ([=12=] as? IndexPath) == nil } // [=12=] is a double optional, so I unwrap it like this
.bind(to: button!.rx.isHidden)
.disposed(by: disposeBag)
}
但是,当我 select 一个项目时,操作按钮根本不会出现。
我也尝试观察 indexPathsForSelectedRows
,但结果相同。
然后我尝试分别订阅itemSelected
和itemDeselected
:
[actionButton1, actionButton2, actionButton3].forEach { (button) in
button?.isHidden = true
self.tableView.rx.itemSelected.subscribe(onNext: {
_ in
button?.isHidden = false
}).disposed(by: disposeBag)
self.tableView.rx.itemDeselected.subscribe(onNext: {
[weak self] _ in
button?.isHidden = (self?.tableView.indexPathForSelectedRow ?? nil) == nil
}).disposed(by: disposeBag)
}
这一次,当我 select 一行时,按钮正确显示。
然而,当可观察数据源发生变化时,selected 行被删除,导致 table 视图不再有任何 selected 行,操作按钮不会消失。
当 table 视图没有任何 select 编辑的行时,如何使我的操作按钮消失?
请注意,我不关心 哪个 行是 select 编辑的。我只想知道 是否 任何行 selected。换句话说,只要语句 "the table view has at least one selected row" 从 true 变为 false,或从 false 变为 true,Observable<Bool>
就会发出一个新值。
如果你只使用 RxCocoa 应该这样做:
let itemIsSelected = Observable.merge(
tableView.rx.itemSelected.map { _ in true },
tableViewItems.map { _ in false } // this is the magic you are missing.
)
.startWith(false)
// a much easier way to handle your buttons' hidden state.
for buttonIsHidden in actionButtons.map({ [=10=].rx.isHidden }) {
itemIsSelected
.map { ![=10=] }
.bind(to: buttonIsHidden)
.disposed(by: disposeBag)
}
如果你使用的是 RxDataSources,解决方案更详细:
let itemSelected = tableView.rx.modelSelected(String.self) // or whatever the type is.
let itemIsSelected = Observable.merge(
itemSelected.map { _ in true },
tableViewItems.filter(if: itemSelected) { ![=11=].contains() }
.map { _ in false }
)
.startWith(false)
for buttonIsHidden in actionButtons.map({ [=11=].rx.isHidden }) {
itemIsSelected
.map { ![=11=] }
.bind(to: buttonIsHidden)
.disposed(by: disposeBag)
}
以上使用了我的要点:https://gist.github.com/danielt1263/1a70c4f7b8960d06bd7f1bfa81802cc3
其中包含这个功能:
extension ObservableType {
/// Filters the source observable sequence using a trigger observable sequence.
/// Elements only go through the filter when the trigger has not completed and
/// its last element produces a true value from the pred. If either source or trigger error's, then the source errors.
///
/// - Parameters:
/// - trigger: The sequence to compare with.
/// - pred: The predicate function to determine if the element should pass through.
/// - Returns: An Observable of the same type that passed the filter test.
func filter<O>(if trigger: O, _ pred: @escaping (Element, O.Element) -> Bool) -> Observable<Element> where O: ObservableType {
return self.withLatestFrom(trigger) { ([=12=], ) }
.filter { pred([=12=].0, [=12=].1) }
.map { [=12=].0 }
}
}
在我的应用程序中,我有一个包含大量行的 table 视图。 table 视图由一个可观察对象填充。我正在使用 RxTableViewSectionedAnimatedDataSource
.
table 视图的行表示用户可以对其执行操作的某种项目。这意味着我希望某些按钮在行被 selected 时出现,并且我希望这些按钮在没有行被 selected 时消失。这些按钮是用户可以对项目执行的操作。
我想我可以观察 indexPathForSelectedRow
属性 并将其绑定到 button.rx.isHidden
,像这样:
[actionButton1, actionButton2, actionButton3].forEach { (button) in
button?.isHidden = true // they are always hidden initially
self.tableView.rx.observe(IndexPath?.self, "indexPathForSelectedRow")
.map { ([=12=] as? IndexPath) == nil } // [=12=] is a double optional, so I unwrap it like this
.bind(to: button!.rx.isHidden)
.disposed(by: disposeBag)
}
但是,当我 select 一个项目时,操作按钮根本不会出现。
我也尝试观察 indexPathsForSelectedRows
,但结果相同。
然后我尝试分别订阅itemSelected
和itemDeselected
:
[actionButton1, actionButton2, actionButton3].forEach { (button) in
button?.isHidden = true
self.tableView.rx.itemSelected.subscribe(onNext: {
_ in
button?.isHidden = false
}).disposed(by: disposeBag)
self.tableView.rx.itemDeselected.subscribe(onNext: {
[weak self] _ in
button?.isHidden = (self?.tableView.indexPathForSelectedRow ?? nil) == nil
}).disposed(by: disposeBag)
}
这一次,当我 select 一行时,按钮正确显示。
然而,当可观察数据源发生变化时,selected 行被删除,导致 table 视图不再有任何 selected 行,操作按钮不会消失。
当 table 视图没有任何 select 编辑的行时,如何使我的操作按钮消失?
请注意,我不关心 哪个 行是 select 编辑的。我只想知道 是否 任何行 selected。换句话说,只要语句 "the table view has at least one selected row" 从 true 变为 false,或从 false 变为 true,Observable<Bool>
就会发出一个新值。
如果你只使用 RxCocoa 应该这样做:
let itemIsSelected = Observable.merge(
tableView.rx.itemSelected.map { _ in true },
tableViewItems.map { _ in false } // this is the magic you are missing.
)
.startWith(false)
// a much easier way to handle your buttons' hidden state.
for buttonIsHidden in actionButtons.map({ [=10=].rx.isHidden }) {
itemIsSelected
.map { ![=10=] }
.bind(to: buttonIsHidden)
.disposed(by: disposeBag)
}
如果你使用的是 RxDataSources,解决方案更详细:
let itemSelected = tableView.rx.modelSelected(String.self) // or whatever the type is.
let itemIsSelected = Observable.merge(
itemSelected.map { _ in true },
tableViewItems.filter(if: itemSelected) { ![=11=].contains() }
.map { _ in false }
)
.startWith(false)
for buttonIsHidden in actionButtons.map({ [=11=].rx.isHidden }) {
itemIsSelected
.map { ![=11=] }
.bind(to: buttonIsHidden)
.disposed(by: disposeBag)
}
以上使用了我的要点:https://gist.github.com/danielt1263/1a70c4f7b8960d06bd7f1bfa81802cc3
其中包含这个功能:
extension ObservableType {
/// Filters the source observable sequence using a trigger observable sequence.
/// Elements only go through the filter when the trigger has not completed and
/// its last element produces a true value from the pred. If either source or trigger error's, then the source errors.
///
/// - Parameters:
/// - trigger: The sequence to compare with.
/// - pred: The predicate function to determine if the element should pass through.
/// - Returns: An Observable of the same type that passed the filter test.
func filter<O>(if trigger: O, _ pred: @escaping (Element, O.Element) -> Bool) -> Observable<Element> where O: ObservableType {
return self.withLatestFrom(trigger) { ([=12=], ) }
.filter { pred([=12=].0, [=12=].1) }
.map { [=12=].0 }
}
}