简体   繁体   中英

RxSwift calling bind fires immediately vs subscribe(onNext: )

Everything I've read says that bind(to:) calls subscribe(onNext:) within it. So I assume I should be able to swap out some stuff, but when I use `bind(to:) the thing it's binding to fires immediately. Here's my example:

ButtonCollectionViewCell

class ButtonCollectionViewCell: UICollectionViewCell {

    lazy var buttonTapped: Observable<Void> = { _buttonTapped.asObservable() }()
    private var _buttonTapped = PublishSubject<Void>()
    private var disposeBag = DisposeBag()

    @IBOutlet private weak var textLabel: UILabel!
    @IBOutlet private weak var actionButton: UIButton!

    // MARK: - Lifecycle

    override func awakeFromNib() {
        super.awakeFromNib()

        actionButton.rx.tap.bind(to: _buttonTapped).disposed(by: disposeBag)
    }

    override func prepareForReuse() {
        disposeBag = DisposeBag()
    }

}

Now when I do the following below everything works as expected and it prints to the console when I tap the button

ViewController with a collection view

func createButtonCell() {
    let buttonCell = ButtonCollectionViewCell() // there's more code to create it, this is just for simplicity
    buttonCell.buttonTapped.subscribe { _ in
        print("tapped")
    }.disposed(by: disposeBag)
    return buttonCell
}

However, if I change the above to:

func createButtonCell() {
    let buttonCell = ButtonCollectionViewCell()
    buttonCell.buttonTapped.bind(to: buttonTapped)
    return buttonCell
}

private func buttonTapped(_ sender: Observable<Void>) {
    print("tapped")
}

The "tapped" is printed out right before I get to the cell when scrolling which I assume is when it's being created.

I don't understand this. I thought I could almost swap out the implementations? I would like to use the second example above there as I think it's neater but can't figure out how.

Your two examples are not identical...

In the first example you have: .subscribe { _ in print("tapped") } which is not a subscribe(onNext:) call. The last closure on the subscribe is being used, not the first. IE, you are calling subscribe(onDisposed:) .

Also, your ButtonCollectionViewCell is setup wrong. You bind in the awakeFromNib() which is only called once, and dispose in the prepareForReuse() which is called multiple times. One of the two needs to be move to a more appropriate place...

UPDATE

You could either rebind your subject after reseating the disposeBag, or you could just not put the chain in the dispose bag in the first place by doing:

_ = actionButton.rx.tap
    .takeUntil(rx.deallocating)
    .bind(to: _buttonTapped)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM