[英]RxSwift modify tableview cell on select
我的應用程序中有一個表格視圖。 我使用以下代碼為此表生成了數據源
struct ContactNameNumberBlockStatus {
var contactThumbnail: Data?
var contactName : String
var contactNumber: String
var blockStatus : Bool
}
class BlockListTableViewCell: UITableViewCell {
@IBOutlet weak var contactImage: UIImageView!
@IBOutlet weak var contactName: UILabel!
@IBOutlet weak var contactNumber: UILabel!
@IBOutlet weak var blockButton: UIButton!
var eachCell : ContactNameNumberBlockStatus! {
didSet {
// setting ui
}
}
}
private func showTableContent(data : Observable<[ContactNameNumberBlockStatus]>) {
data.bindTo(tableView.rx.items(
cellIdentifier: "BlockListTableViewCell")) {
row, contributor, cell in
if let cell2 = cell as? BlockListTableViewCell {
cell2.eachCell = contributor
}
}.addDisposableTo(disposeBag)
}
現在,當我點擊單元格時,我想通過顯示/隱藏blockButton
提到的blockButton
來更新 ui
這該怎么做 ??
在使用 rx 之前,我使用了表視圖的 didSelectRowAt 如下
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
contacts[indexPath.row].blockStatus = false
self?.tableView.reloadData()
}
我發現tableView.rx.itemSelected
與上面的didSelectRowAt
相同,但我找不到如何使用以下代碼更新表格視圖
tableView.rx.itemSelected
.subscribe(onNext: { [weak self]indexPath in
}).addDisposableTo(disposeBag)
那么如何更新單元格呢?
您可以像這樣訪問單元格
tableView.rx.itemSelected
.subscribe(onNext: { [weak self] indexPath in
let cell = self?.tableview.cellForRow(at: indexPath) as? SomeCellClass
cell.button.isEnabled = false
}).addDisposableTo(disposeBag)
我不太喜歡接受的答案,因為在那個答案中,沒有跟蹤塊狀態的模型。 相反,它只是禁用按鈕。 重要的是讓您的視圖狀態遵循模型並且接受的答案忽略了這一點。
下面顯然更復雜,但它設置模型並使視圖的狀態反映底層模型而不是避開模型。
enum Input {
case reset([ContactNameNumberBlockStatus])
case blockTapped(UUID)
}
struct State {
var order: [UUID] = []
var values: [UUID: ContactNameNumberBlockStatus] = [:]
}
let taps = PublishSubject<UUID>()
let state = Observable.merge(
contacts.map { Input.reset($0) },
taps.map { Input.blockTapped($0) }
)
.scan(into: State()) { (state, input) in
switch input {
case .reset(let contacts):
state.order = contacts.map { _ in UUID() }
state.values = Dictionary.init(zip(state.order, contacts), uniquingKeysWith: { lhs, _ in lhs })
case .blockTapped(let uuid):
state.values[uuid]!.blockStatus = true
}
}
state
.map { $0.order }
.bind(to: tableView.rx.items(cellIdentifier: "BlockListTableViewCell", cellType: BlockListTableViewCell.self)) { row, uuid, cell in
let cellState = state.compactMap { $0.values[uuid] }
cell.disposeBag.insert(
cellState.map { $0.contactThumbnail.flatMap { UIImage(data: $0) } }.bind(to: cell.contactImage.rx.image),
cellState.map { $0.contactName }.bind(to: cell.contactName.rx.text),
cellState.map { $0.contactNumber }.bind(to: cell.contactNumber.rx.text),
cellState.map { $0.blockStatus }.bind(to: cell.blockButton.rx.isHidden),
cell.blockButton.rx.tap.map { uuid }.bind(to: taps)
)
}
.disposed(by: disposeBag)
上面的代碼設置了一個狀態機,用於跟蹤用戶並根據需要更新用戶模型,從而導致視圖更新。 它更具可擴展性; 當發現新的用戶輸入時,只需在Input
類型中添加一個 case。 此外,當發現新狀態時,可以將其添加到 State 類型中。
該代碼還有一個額外的好處; 更新模型中項目的狀態不會導致整個表視圖重新加載。 只有那個單元格會被改變。
//獲取模型訪問權限
tableView.rx.modelSelected(Item.self)
.subscribe(onNext: { [weak self] model in
guard let self = self else { return }
self.selectedItem = model
}).disposed(by: disposeBag)
//訪問indexPath
eg: var names = ["A", "B", "C"]
tableView.rx.itemSelected
.subscribe(onNext: { [weak self] indexPath in
guard let self = self else { return }
self.selectedName = self.names[indexPath.row]
self.performSegue(withIdentifier: "ItemDetail", sender: self)
}).disposed(by: disposeBag)
如果您想獲得模型的句柄以及索引路徑,您可以在文件中同時擁有
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.