ios – 在UICollectionViewCell中为UIButton设置rx.tap的问题 – RxSwift 3

前端之家收集整理的这篇文章主要介绍了ios – 在UICollectionViewCell中为UIButton设置rx.tap的问题 – RxSwift 3前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我为1 UIButton订阅了2次:

>首次订阅,用于在每次点击时更新UI
>第二次订阅,用于在累积点击后每1秒更新一次Web服务上的值.

码:

class ProductionSize {
    var id : Int?
    var size: Int = 0
    var name: String = ""
}

class ProductionCell: UICollectionViewCell {
    var rxBag = DisposeBag()


    // this will be set in the (cellForItemAt indexPath: IndexPath) of collection view
    var productionSize: ProductionSize? {
        didSet {
            showProductionSize()
            prepareButton()
        }
    }

    func showProductionSize() {
        // ... code for showing ProductionSize in labels
    }

    func prepareButton() {
        // This for subscribing for every click for displaying purpose

        btn_increase.rx.tap
            .subscribe(){event in 
                self.increaseClicked() 
            }
            .addDisposableTo(rxBag)

        // this for subscribing for sending webservice request after 1 second of clicking the button (so that if user click it quickly i send only last request)

        btn_increase.rx.tap
            .debounce(1.0,scheduler: MainScheduler.instance)
            .subscribe(){ event in self.updateOnWS() }
            .addDisposableTo(rxBag)
    }

    func increaseClicked() {
        productionSize.size = productionSize.size + 1
        showProductionSize()
    }

    func updateOnWS() {
        // code for updating on webservice with Moya,RxSwift and Alamofire§
    }


    // when scrolling it gets called to dispose subscribtions
    override func prepareForReuse() {
        rxBag = DisposeBag()
    }

}

问题:

由于dispose发生在prepareForReuse()上,如果我多次单击该按钮并立即滚动,webservice调用将被处理掉而不会更新.

我试过的:

>将addDisposableTo(vc?.rx_disposableBag)添加到父ViewController DisposableBag.

问题,订阅累积和每次点击updateWS()多次调用,在每个滚动上订阅,从未处理.
>我试图从prepareForReuse()中删除disposableBag重新初始化.

问题是,每次点击都会调用对重复和累积的按钮的订阅以及许多webservice调用.

题:
如何让debounce订阅调到最后,并且从不重复多次订阅(如果是addDisposableTo viewController Bag)?

解决方法

Added addDisposableTo(vc?.rx_disposableBag) to the parent ViewController DisposableBag.

The problem,the subscribtions accumulated and on every click the updateWS() called many times which is subscribed on every scroll and never disposed.

由于您订阅按钮的点击方式,您的self.updateOnWS()可能会被多次调用.

btn_increase.rx.tap
        .debounce(1.0,scheduler: MainScheduler.instance)
        .subscribe(){ event in self.updateOnWS() }
        .addDisposableTo(rxBag)

如您所见,您使用subscribe()方法订阅所有事件.这意味着所有Rx事件(onNext,onError,onCompleted,onSubscribed和onDisposed)都会触发self.updateOnWS().您可以通过打印事件对象来检查是否是这种情况,以查看触发了什么事件.

仅在onNext上订阅

可能的修复可能是仅订阅onNext操作.

btn_increase.rx.tap
        .debounce(1.0,scheduler: MainScheduler.instance)
        .subscribe(onNext: { [weak self] (_ : Void) in
               self?.updateOnWS() 
        })
        .addDisposableTo(vc?.rxdisposableBag)

通过使用视图控制器的DisposeBag,您可以确保即使单元格被放置(向下滚动时)操作仍然继续.但是,如果在单元格处理时需要它来处置订阅,请使用单元格的DisposeBag,而不是视图控制器.

旁注 – 内存泄漏

请注意,对self的引用被指定为弱,以便您可以防止发生内存泄漏.通过将其指定为弱,它将为您提供可选的self参考.

如果不这样做,你为onNext块创建的闭包将保留对self的强引用,这就是你的UICollectionViewCell,而UICollectionViewCell又拥有我们正在讨论的闭包.

这最终会导致内存不足崩溃.请参阅我在您的问题的评论中发布的参考,以获取有关错误引用self导致的内存泄漏的更多内容.

猜你在找的iOS相关文章