RxCocoa 中的 UICollectionViewDelegate

UICollectionViewDelegate in RxCocoa

我为 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 编写扩展?

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

collectionView(_:shouldHighlightItemAt:) 期望您 return 一个 Bool 值。所以你不能使用 methodInvoked(_:).

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

Delegate methods that have non void return value can't be observed directly using this method because:

  • those methods are not intended to be used as a notification mechanism, but as a behavior customization mechanism

  • there is no sensible automatic way to determine a default return value

不过,有一个建议可以帮助您实现目标:

In case observing of delegate methods that have return type is required, it can be done by manually installing a PublishSubject or BehaviorSubject and implementing delegate method.

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

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 源代码中获取它并修改它以满足您的需要。所以理论上这应该可行,但您可能需要稍微调整一下 ;-)