我正在努力应对以下挑战。我使用包含开关的自定义单元格创建了表格 View 。我只想打开一个开关,例如,发射后我打开第三个开关,然后我打开第七个开关,因此第三个开关关闭,依此类推。我对单元使用 rx + 协议(protocol),并且一直不明白如何确定切换哪个开关。以前我打算使用过滤器或映射在 dataSource 数组中查找哪个开关打开并以某种方式处理这个问题,但现在我搞砸了。我不确定不使用 TableView 委托(delegate)方法是否可行。非常感谢,希望有人能解释我错在哪里。
//我的单元格是这样的:
//CellViewModel 实现
import Foundation
import RxSwift
protocol ViewModelProtocol {
var bag:DisposeBag {get set}
func dispose()
}
class ViewModel:ViewModelProtocol {
var bag = DisposeBag()
func dispose() {
self.bag = DisposeBag()
}
}
protocol CellViewModelProtocol:ViewModelProtocol {
var isSwitchOn:BehaviorSubject<Bool> {get set}
}
class CellVM:ViewModel, CellViewModelProtocol {
var isSwitchOn: BehaviorSubject<BooleanLiteralType> = BehaviorSubject(value: false)
let internalBag = DisposeBag()
override init() {
}
}
//我的 Cell 实现
import UIKit
import RxSwift
import RxCocoa
class Cell:UITableViewCell {
static let identifier = "cell"
@IBOutlet weak var stateSwitch:UISwitch!
var vm:CellViewModelProtocol? {
didSet {
oldValue?.dispose()
self.bindUI()
}
}
var currentTag:Int?
var bag = DisposeBag()
override func awakeFromNib() {
super.awakeFromNib()
self.bindUI()
}
override func prepareForReuse() {
super.prepareForReuse()
self.bag = DisposeBag()
}
private func bindUI() {
guard let vm = self.vm else { return }
self.stateSwitch.rx.controlEvent(.valueChanged).withLatestFrom(self.stateSwitch.rx.value).observeOn(MainScheduler.asyncInstance).bind(to: vm.isSwitchOn).disposed(by: vm.bag)
}
}
//TableViewController 实现
import UIKit
import RxSwift
import RxCocoa
class TableViewController: UITableViewController {
private var dataSource:[CellViewModelProtocol] = []
var vm = TableViewControllerVM()
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.estimatedRowHeight = 70
self.tableView.rowHeight = UITableView.automaticDimension
self.bindUI()
}
private func bindUI() {
vm.dataSource.observeOn(MainScheduler.asyncInstance).bind { [weak self] (dataSource) in
self?.dataSource = dataSource
self?.tableView.reloadData()
}.disposed(by: vm.bag)
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.dataSource.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: Cell.identifier, for: indexPath) as! Cell
if cell.vm == nil {
cell.vm = CellVM()
}
return cell
}
}
class TableViewControllerVM:ViewModel {
var dataSource:BehaviorSubject<[CellViewModelProtocol]> = BehaviorSubject(value: [])
let internalBag = DisposeBag()
override init() {
super.init()
dataSource.onNext(createDataSourceOf(size: 7))
self.handleState()
}
private func createDataSourceOf(size:Int) -> [CellViewModelProtocol] {
var arr:[CellViewModelProtocol] = []
for _ in 0..<size {
let cell = CellVM()
arr.append(cell)
}
return arr
}
private func handleState() {
}
}
最佳答案
也许这段代码会帮助你:
extension TableViewController {
// called from viewDidLoad
func bind() {
let cells = (0..<7).map { _ in UUID() } // each cell needs an ID
let active = ReplaySubject<UUID>.create(bufferSize: 1) // tracks which is the currently active cell by ID
Observable.just(cells) // wrap the array in an Observable
.bind(to: tableView.rx.items(cellIdentifier: "Cell", cellType: Cell.self)) { _, element, cell in
// this subscription causes the inactive cells to turn off
active
.map { $0 == element }
.bind(to: cell.toggleSwitch.rx.isOn)
.disposed(by: cell.disposeBag)
// this subscription watches for when a cell is set to on.
cell.toggleSwitch.rx.isOn
.filter { $0 }
.map { _ in element }
.bind(to: active)
.disposed(by: cell.disposeBag)
}
.disposed(by: disposeBag)
}
}
关于ios - 只有一个开关打开,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62260402/