RxCocoa 中的 UICollectionViewDelegate

Posted

技术标签:

【中文标题】RxCocoa 中的 UICollectionViewDelegate【英文标题】:UICollectionViewDelegate in RxCocoa 【发布时间】:2018-11-04 16:10:23 【问题描述】:

我为 UICollectionView 编写了一个扩展,它将监听委托的 shouldHighlightItemAt 方法,但它不调用。

public var shouldHighlightItem: ControlEvent<IndexPath> 

    let source = self.delegate.methodInvoked(#selector(UICollectionViewDelegate.collectionView(_:shouldHighlightItemAt:)))
        .map  a in
            return try self.castOrThrow(IndexPath.self, a[1])
    

    return ControlEvent(events: source)

rx shouldHighlightItemAt的UICollectionView怎么写扩展?

【问题讨论】:

【参考方案1】:

您不能将 methodInvoked(_:) 与具有非 void 返回类型的委托方法一起使用。

collectionView(_:shouldHighlightItemAt:) 期望您返回 Bool 值。所以你不能使用methodInvoked(_:)

如果您查看 methodInvoked(_:) 的实现,它会解释为什么这不起作用:

不能观察到没有void返回值的委托方法 直接用这个方法 因为:

这些方法并非旨在用作通知机制,而是用作行为自定义机制

没有明智的自动方法来确定默认返回值

但是有一个建议,你可以如何实现你正在尝试做的事情:

如果观察具有返回类型的委托方法是 需要,可以通过 手动安装PublishSubjectBehaviorSubject 并实现委托方法。

在你的情况下,它会像这样工作:

RxCollectionViewDelegateProxy 中添加“PublishSubject”并实现UICollectionViewDelegate 方法:

let shouldHighlightItemAtIndexPathSubject = PublishSubject<IndexPath>

public func collectionView(_ collectionView: UICollectionView, shouldHighlightItemAt indexPath: IndexPath) -> Bool 
    shouldHighlightItemAtIndexPathSubject.on(.next(indexPath))
    return self._forwardToDelegate?.collectionView(collectionView, shouldHighlightItemAt: indexPath) ?? true // default value

在您的 UICollectionView RxExtension 中,您可以像这样公开所需的 Observable:

public var property: Observable<IndexPath> 
    let proxy = RxCollectionViewDelegateProxy.proxy(for: base)
    return proxy.shouldHighlightItemAtIndexPathSubject.asObservable()

我没有对此进行测试,我只是从 RxCocoa 源代码中获取它并对其进行修改以满足您的需求。所以理论上这应该可行,但你可能需要稍微调整一下;-)

【讨论】:

以上是关于RxCocoa 中的 UICollectionViewDelegate的主要内容,如果未能解决你的问题,请参考以下文章

调用中的 RxCocoa 额外参数

如何将控制事件添加到 RxCocoa 中的自定义按钮?

Swift4 中的 RxCocoa 映射可选错误,带有“无法转换类型“字符串?”的值

使用 RxSwift/RxCocoa 制作的 TableView 在绑定到的变量中的数据更改后出现故障

如何测试 RxSwift 变量和 RxCocoa Observable 之间的 UI 绑定?

RxCocoa - 为啥 PublishRelay 没有 asDriver() 方法?