18

我的应用程序中有一个表格视图。我使用以下代码为该表生成了数据源

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顶部提到的来更新 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)

那么如何更新单元格呢?

4

3 回答 3

73

您可以像这样访问单元格

tableView.rx.itemSelected
  .subscribe(onNext: { [weak self] indexPath in
    let cell = self?.tableview.cellForRow(at: indexPath) as? SomeCellClass
    cell.button.isEnabled = false
  }).addDisposableTo(disposeBag)
于 2017-02-06T13:32:00.147 回答
3

我不是公认答案的忠实拥护者,因为在该答案中,没有模型可以跟踪块状态。相反,它只是禁用按钮。让您的视图状态遵循模型很重要,而接受的答案会忽略这一点。

以下显然更复杂,但它设置了模型并使视图的状态反映了底层模型,而不是避开模型。

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类型中添加一个案例。此外,当发现新状态时,可以将其添加到 State 类型中。

该代码还有一个额外的好处;更新模型中项目的状态不会导致整个表视图重新加载。只有那个单元格会被改变。

于 2020-10-19T11:53:02.780 回答
1

//访问模型

            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)

如果您想获取模型的句柄以及索引路径,则可以在文件中同时拥有两者

于 2020-10-18T23:27:04.973 回答