RXSwift结合UITableView如何根据Observable值动态切换行侧滑操作
实现思路
UITableView的trailingSwipeActionsConfigurationForRowAt代理方法需要同步返回侧滑配置,因此我们需要先持有当前最新的商品列表数据,直接读取对应行的isEnabled属性判断要展示的侧滑按钮。
步骤1:维护本地最新商品列表
因为你的interactionService.products是Observable类型,我们需要订阅它的更新,把最新值存在本地变量中,方便同步读取:
// ViewController 新增属性 private var currentProducts: [Product] = [] private let disposeBag = DisposeBag() // 在viewDidLoad中添加订阅逻辑 override func viewDidLoad() { super.viewDidLoad() // 其他初始化逻辑... // 订阅商品列表更新,同步到本地变量 self.interactionService.products .subscribe(onNext: { [weak self] products in guard let self = self else { return } self.currentProducts = products self.tableView.reloadData() // 刷新列表更新侧滑状态 }) .disposed(by: self.disposeBag) }
步骤2:修改侧滑代理方法
新增inStockAction逻辑,根据当前商品的isEnabled属性切换要返回的侧滑配置:
func tableView( _ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath ) -> UISwipeActionsConfiguration? { // 安全校验行索引是否合法 guard indexPath.row < currentProducts.count else { return nil } let currentProduct = currentProducts[indexPath.row] // 1. 定义Sold Out操作 let soldOutAction = UIContextualAction( style: .normal, title: "Sold Out" ) { [weak self] (_, _, completionHandler) in guard let self = self else { return } self.interactionService.products .map({ $0[indexPath.row] }) .take(1) .do(onNext: { [weak self] product in self?.analytics.userMarkedAsSoldOut(product: product.productID) }) .flatMapLatest({ self.interactionService.disableProduct($0) }) .subscribe(onCompleted: { completionHandler(true) }) .disposed(by: self.disposeBag) } soldOutAction.backgroundColor = UIColor(red: 0.996, green: 0.09, blue: 0.478, alpha: 1) // 2. 新增In Stock操作 let inStockAction = UIContextualAction( style: .normal, title: "In Stock" ) { [weak self] (_, _, completionHandler) in guard let self = self else { return } self.interactionService.products .map({ $0[indexPath.row] }) .take(1) .do(onNext: { [weak self] product in // 对应上报标记为在售的事件,可根据实际需求修改 self?.analytics.userMarkedAsInStock(product: product.productID) }) .flatMapLatest({ self.interactionService.enableProduct($0) }) .subscribe(onCompleted: { completionHandler(true) }) .disposed(by: self.disposeBag) } inStockAction.backgroundColor = UIColor(red: 0.204, green: 0.78, blue: 0.349, alpha: 1) // 示例绿色,可自定义 // 3. 根据isEnabled判断要返回的操作 let actions: [UIContextualAction] if currentProduct.isEnabled { actions = [soldOutAction] } else { actions = [inStockAction] } let config = UISwipeActionsConfiguration(actions: actions) config.performsFirstActionWithFullSwipe = false return config }
补充说明
如果你的interactionService.products本身是BehaviorRelay/BehaviorSubject类型,已经存储了当前最新值,也可以直接读取它的value属性判断,不需要额外维护currentProducts变量。
内容的提问来源于stack exchange,提问作者Mike Simz
相关产品推荐
相关产品推荐

