RxSwift 和 AlertAction
RxSwift and AlertAction
我有带有 UIAlertAction 的 Tableview。当我按下一个单元格时,会出现一个弹出窗口,然后我可以决定执行哪个操作。在 Ok 操作(单击按钮)期间,我想观察单元格的数据并在 ViewModel 中接收它。但是有问题。
当我第一次按下时没有任何值,如果我只是单击一个单元格,数据仍会发送到 ViewModel。如果我点击更多 UIAlertAction 弹出窗口,发送数据就会增加。例如:第一次点击 - 无,第二次点击 - 值 1,第三次点击值 1, 1, 1 等等。
如何从第一次单击 UIAlertAction 弹出窗口开始观察单元格以及如何仅获取数据示例?
ViewController:
func bindTableView() {
viewModel.stationItems.bind(to: addTableView.rx.items(cellIdentifier: "addCell", cellType: AddTableViewCell.self)) { (row, item, cell)
in
cell.cellAdd = item
}.disposed(by: disposeBag)
addTableView.rx.modelSelected(StationItem.self)
.subscribe(onNext: { item in
let alert = UIAlertController(title: "Add Station", message: "Do you want to add a station to your favorites?", preferredStyle: .alert)
let ok = UIAlertAction(title: "Ok", style: .default, handler: { action in
self.addTableView.rx.modelSelected(StationItem.self)
.bind(to: self.viewModel.stationItem)
.disposed(by: self.disposeBag)
self.viewModel.addStationItem()
})
alert.addAction(ok)
let cancel = UIAlertAction(title: "Cancel", style: .default, handler: { action in
})
alert.addAction(cancel)
DispatchQueue.main.async(execute: {
self.present(alert, animated: true)
})
}).disposed(by: disposeBag)
viewModel.fetchStations()
}
视图模型:
let stationItem = PublishSubject<StationItem>()
func addStationItem() {
stationItem.subscribe(onNext: {(data) in
print("Data: \(data)")
})
.disposed(by: disposeBag)
print("ADD:")
}
问题是您对 modelSelected
的追溯订阅。请记住,每次调用该函数时,您都会得到一个 new 可观察对象。从订阅的那一刻起,无论什么时候点击,它都会告诉你,但它不会告诉你上一次点击,即导致警报首先出现的那个。
这里要做的第一件事是创建一个可重用的函数,让您可以创建和显示警报视图。每当您想向用户询问某事时,请使用这种模式:
extension UIViewController {
func presentAlert(title: String?, message: String?) -> Observable<Void> {
let result = PublishSubject<Void>()
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
let ok = UIAlertAction(title: "OK", style: .default, handler: { _ in
result.onNext(())
result.onCompleted()
})
let cancel = UIAlertAction(title: "Cancel", style: .cancel) { _ in
result.onCompleted()
}
alert.addAction(ok)
alert.addAction(cancel)
present(alert, animated: true)
return result
}
}
如果您要为视图模型使用命令式输入,请一直保持一致性:
final class ViewModel {
let stationItems = PublishSubject<[StationItem]>()
func addStationItem(_ item: StationItem) {
print("ADD:")
}
func fetchStations() {
// do your fetching and load `stationItems`.
}
}
然后在你的view controller的bind函数中,你可以使用一个flatMap来调用上面的:
addTableView.rx.modelSelected(StationItem.self)
.flatMapFirst { [unowned self] item in
self.presentAlert(title: "Add Station", message: "Do you want to add a station to your favorites?")
.map { item }
}
.bind { [viewModel] in
viewModel?.addStationItem([=12=])
}
.disposed(by: disposeBag)
你在这里所做的看起来很像 The Binder Architecture。您可能会发现阅读更多相关内容很有启发性。
我有带有 UIAlertAction 的 Tableview。当我按下一个单元格时,会出现一个弹出窗口,然后我可以决定执行哪个操作。在 Ok 操作(单击按钮)期间,我想观察单元格的数据并在 ViewModel 中接收它。但是有问题。 当我第一次按下时没有任何值,如果我只是单击一个单元格,数据仍会发送到 ViewModel。如果我点击更多 UIAlertAction 弹出窗口,发送数据就会增加。例如:第一次点击 - 无,第二次点击 - 值 1,第三次点击值 1, 1, 1 等等。 如何从第一次单击 UIAlertAction 弹出窗口开始观察单元格以及如何仅获取数据示例?
ViewController:
func bindTableView() {
viewModel.stationItems.bind(to: addTableView.rx.items(cellIdentifier: "addCell", cellType: AddTableViewCell.self)) { (row, item, cell)
in
cell.cellAdd = item
}.disposed(by: disposeBag)
addTableView.rx.modelSelected(StationItem.self)
.subscribe(onNext: { item in
let alert = UIAlertController(title: "Add Station", message: "Do you want to add a station to your favorites?", preferredStyle: .alert)
let ok = UIAlertAction(title: "Ok", style: .default, handler: { action in
self.addTableView.rx.modelSelected(StationItem.self)
.bind(to: self.viewModel.stationItem)
.disposed(by: self.disposeBag)
self.viewModel.addStationItem()
})
alert.addAction(ok)
let cancel = UIAlertAction(title: "Cancel", style: .default, handler: { action in
})
alert.addAction(cancel)
DispatchQueue.main.async(execute: {
self.present(alert, animated: true)
})
}).disposed(by: disposeBag)
viewModel.fetchStations()
}
视图模型:
let stationItem = PublishSubject<StationItem>()
func addStationItem() {
stationItem.subscribe(onNext: {(data) in
print("Data: \(data)")
})
.disposed(by: disposeBag)
print("ADD:")
}
问题是您对 modelSelected
的追溯订阅。请记住,每次调用该函数时,您都会得到一个 new 可观察对象。从订阅的那一刻起,无论什么时候点击,它都会告诉你,但它不会告诉你上一次点击,即导致警报首先出现的那个。
这里要做的第一件事是创建一个可重用的函数,让您可以创建和显示警报视图。每当您想向用户询问某事时,请使用这种模式:
extension UIViewController {
func presentAlert(title: String?, message: String?) -> Observable<Void> {
let result = PublishSubject<Void>()
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
let ok = UIAlertAction(title: "OK", style: .default, handler: { _ in
result.onNext(())
result.onCompleted()
})
let cancel = UIAlertAction(title: "Cancel", style: .cancel) { _ in
result.onCompleted()
}
alert.addAction(ok)
alert.addAction(cancel)
present(alert, animated: true)
return result
}
}
如果您要为视图模型使用命令式输入,请一直保持一致性:
final class ViewModel {
let stationItems = PublishSubject<[StationItem]>()
func addStationItem(_ item: StationItem) {
print("ADD:")
}
func fetchStations() {
// do your fetching and load `stationItems`.
}
}
然后在你的view controller的bind函数中,你可以使用一个flatMap来调用上面的:
addTableView.rx.modelSelected(StationItem.self)
.flatMapFirst { [unowned self] item in
self.presentAlert(title: "Add Station", message: "Do you want to add a station to your favorites?")
.map { item }
}
.bind { [viewModel] in
viewModel?.addStationItem([=12=])
}
.disposed(by: disposeBag)
你在这里所做的看起来很像 The Binder Architecture。您可能会发现阅读更多相关内容很有启发性。