我们有一个视图控制器MainCollectionView,其中包含一个带有许多单元格FooCell的集合视图。在每个FooCell内部,都有一个收集视图和一个BarCell单元列表。

如何在BarCell中将按钮点击事件传播到MainCollectionView

这就是我们所拥有的:

class FooCell: ... {

    private let barCellButtonTappedSubject: PublishSubject<Void> = PublishSubject<Void>()
    var barCellButtonTappedObservable: Observable<Void> {
        return barCellButtonTappedSubject.asObserver()
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeue(...)

        if let cell = cell as BarCell {
            cell.button.rx.tap.bind { [weak self] in
                self?.barCellButtonTappedSubject.onNext(())
            }.disposed(by: cell.rx.reusableDisposeBag)
        }

        return cell
    }
}

class MainCollectionView: ... {

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeue(...)

        if let cell = cell as FooCell {
            cell.barCellButtonTappedObservable.subscribe { [weak self] in
                // Do other stuff when the button inside bar cell is tapped.
            }.disposed(by: cell.rx.reusableDisposeBag)
        }

        return cell
    }
}

在我阅读有关 ControlEvent 之前,此方法将起作用:
  • 它永远不会失败o​​jit_rli
  • 它不会在订阅
  • 上发送任何初始值
  • 它将在释放控件时完成序列
  • 它永远不会出错
  • 它在MainScheduler.instance上传递事件

    似乎更适合在ControlEvent中使用FooCell:
    private let barCellButtonTappedSubject: PublishSubject<Void> = PublishSubject<Void>()
    var barCellButtonTappedObservable: Observable<Void> {
        return barCellButtonTappedSubject.asObserver()
    }
    

    将此barCellButtonTappedObservable转换为ControlEvent的正确方法是什么?还是有其他更好的主意将嵌套单元格中的ControlEvent传播到外部视图控制器?

    最佳答案

    我个人更喜欢将RxAction用于此类内容,但是由于您已经在单元格中声明了PublishSubject<Void>,因此可以将主题转换为ControlEvent

    controlEvent = ControlEvent<Void>(events: barCellButtonTappedSubject.asObservable())
    

    尽可能直接!但是,如果您只想这样做,那么您甚至不需要barCellButtonTappedSubject
    controlEvent = ControlEvent<Void>(events: cell.button.rx.tap)
    

    实际上,您甚至不需要声明控制事件:)因为cell.button.rx.tap本身是一个控制事件:)因此,如果您在单元格中将按钮声明为 public 属性,则可以在tableView控制器中直接访问其tap控制事件。

    但就我个人而言,我会使用RxAction而不是声明一个publishSubjectcontrolEvent您的FooCell可以要求您的TableViewController采取措施
    class FooCell: ... {
       var cellTapAction : CocoaAction! = nil
    
       func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            let cell = collectionView.dequeue(...)
    
            if let cell = cell as BarCell {
                cell.button.rx.action = cellTapAction
            }
    
            return cell
        }
    }
    

    最后,您的TableViewController / CollectionViewController可以将操作传递为
    class MainCollectionView: ... {
    
        func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            let cell = collectionView.dequeue(...)
    
            if var cell = cell as FooCell {
                cell.cellTapAction = CocoaAction { _ -> Observable<Void> in
                   debugPrint("button in cell tapped")
                   return Observable.just(())
               }
            }
    
            return cell
        }
    }
    

    唯一需要处理的就是是否将cellctionView嵌入到FooCell中,因为即使在传递给action嵌入式collectionView之后也可能会加载deQueReusableCell,所以您甚至必须调整逻辑以在将动作传递给它之后重新加载嵌入的collection视图。 FooCell或任何其他可解决此问题的解决方法:)

    希望对您有所帮助:)我相信使用Action可以使代码更整洁且易于理解。

    关于ios - 如何将`Observable`转换为`ControlEvent`,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52992332/

  • 10-13 04:20