vermotr
vermotr

Reputation: 703

MVVM-C with RxSwift: '[weak self]' in closure

I'm working on an iOS project with RxSwift and I use the MVVM with coordinators pattern.

Here my implementation:

ViewModel:

// MARK: - Private

private let showNextViewSubject = PublishSubject<Void>()

// MARK: - Inputs

var showNextView: AnyObserver<Void> {
    return showNextViewSubject.asObserver()
}

// MARK: - Outputs

var didShowNextView: Observable<Void> {
    return showNextViewSubject.asObservable()
}

ViewController:

private func bindButton() {
    _ = button.rx.tap
        .bind(to: viewModel.showNextView)
        .disposed(by: disposeBag)
}

Coordinator:

self.viewModel.didShowNextView
        .subscribe(onNext: { [weak self] _ in
            self?.showNextView()
        })
        .disposed(by: disposeBag)

My problem is with the [weak self] _ in the coordinator: when I add it, self?.showNextView() is never called, but this works well when I remove it.

Do you know why?

Thanks, Romain

Upvotes: 5

Views: 3202

Answers (4)

Adam Smaka
Adam Smaka

Reputation: 6413

just keep a reference to a this coordinator in his parent coordinator like this

private var childCoordinators = [CoordinatorType]()

so it won't be deallocated

Upvotes: 1

Blackbeard
Blackbeard

Reputation: 662

With Swift 4.2 you could safely rewrite the snippet as:

self.viewModel.didShowNextView
    .subscribe(onNext: { [weak self] in
        guard let self = self else { return } 
        self.showNextView()
    })
    .disposed(by: disposeBag)

This pattern is generally recommended over using self?.

Upvotes: 1

ymutlu
ymutlu

Reputation: 6715

If you do not add [weak self], completion block will retain self and this is not a best way to use blocks. You should have a reference (retain) to your coordinator and it should be released when you are done with it.

Memory management in RxSwift

Upvotes: 1

Joe
Joe

Reputation: 3761

When you get rid of [weak self] the block creates a strong reference to self so that it's not deallocated when any other code is done using it. By making the reference weak self is free to be deallocated which is probably happening. This means there is no other object with a strong reference to self so it is nil and the call won't be made. Getting rid of it could create a retain cycle so you'll want to be careful of that.

Upvotes: 3

Related Questions