RxSwift asDriver 映射和强自我

Posted

技术标签:

【中文标题】RxSwift asDriver 映射和强自我【英文标题】:RxSwift asDriver map and strong self 【发布时间】:2020-02-06 19:46:32 【问题描述】:

我想弄清楚我是否在这里创建了一个保留周期。我想将集合视图的当前偏移量绑定到UIPageControl,如下所示:

collectionView
    .rx
    .contentOffset
    .asDriver()
    .map  Int($0.x) / Int(self.collectionView.frame.width) 
    .drive(pageControl.rx.currentPage)
    .disposed(by: disposeBag)

只是想知道这是否可行,或者该 self 是否会创建一个保留循环?

【问题讨论】:

【参考方案1】:

是的,您的代码创建了一个保留循环,因为您的链保持对 self 的强引用,而 self 保持对链的强引用(通过 disposeBag。)

此外,这样的代码是代码异味,因为您依赖于 map 中的副作用(self.collectionView.frame.width 的值随时间变化),您不应该这样做,因为它会使您的代码无法测试。

这是一个在架构上更正确的解决方案:

class ViewController: UIViewController 

    @IBOutlet weak var collectionView: UICollectionView!
    @IBOutlet weak var pageControl: UIPageControl!

    private let collectionViewFrame = ReplaySubject<CGRect>.create(bufferSize: 1)
    private let disposeBag = DisposeBag()

    deinit 
        collectionViewFrame.onCompleted()
    

    override func viewDidLoad() 
        super.viewDidLoad()

        currentPage(
            offset: collectionView.rx.contentOffset.asObservable(),
            frame: collectionViewFrame.asObservable()
        )
            .bind(to: pageControl.rx.currentPage)
            .disposed(by: disposeBag)
    

    override func viewDidLayoutSubviews() 
        super.viewDidLayoutSubviews()
        collectionViewFrame.onNext(self.collectionView.frame)
    


// This is your logic. Since it is separate from your view code, it can be tested/reused.
func currentPage(offset: Observable<CGPoint>, frame: Observable<CGRect>) -> Observable<Int> 
    return Observable.combineLatest(offset, frame)
        .map  Int($0.0.x) / Int($0.1.width) 

【讨论】:

它有什么副作用?这正是地图应该做的。把一件事变成另一件事。你会如何建议写这篇文章? 我添加了一个示例来说明我将如何做到这一点,但也许我很迂腐。

以上是关于RxSwift asDriver 映射和强自我的主要内容,如果未能解决你的问题,请参考以下文章

tableView.rx.itemSelected 中的 RxSwift 双映射

带有 RxSwift 的搜索栏取消按钮

RXSwift的一些基本交互(OC,Swift,RXSwift对比)

RxSwift 链接请求

为啥 `NotificationCenter+Rx` 在 RxCocoa 而不是 RxSwift

RxSwift - rx.tap 不工作