Memory Leaks in RxSwift
Using RxSwift,
I usually doubt whether generating memory leaks when binding a signal to binders, blocs, or functions. Finally, I decided to write an example listing all situations we usually use.
In the project blow, the NewViewController
would be present from another view controller, touches the NewViewController will dismiss itself.
1 | import UIKit |
We will write codes in the function bindSignals
to test our situations.
Bind single to binder
If the view component has the binder we need, we usually bind the signal to the binder. just like blow:
1 | private func bindSignals() { |
When we bind the relay to the binder isHidden,
we use the self
in the expression, but it won’t lead to memory leaks when we click the view to dismiss the view controller.
Bind single to bloc
1 | private func bindSignals() { |
It’s clear that the bloc references the self
and itself was referenced by the self too, so there is a cycle reference generated, we can add [weak self]
or [unowned self]
in the bloc to break the cycle reference.
Bind single to function
Above two situations is easy to understand. Some times you might not use the bloc but a function, just like blow:
1 | private func bindSignals() { |
When we write the local function bindBtnFunc,
we don’t need to write the keyword self.
But when we dismiss the view controller, we can not see any output in the console. The button and the view controller weren’t released. And you can’t write weak or unowned in a function to break the reference cycle.
Not only local functions but the class member functions also can not be used like this. If you still want to use a function, you must ensure that the function body doesn’t catch the self or any properties of the self. In the example above, you can declare a local variable referencing the self.btn.
Then the function body will catch the local variable instead of the self.btn,
without self,
of course, no reference cycle.
1 | private func bindSignals() { |
Conclusion
Using binders is always safe. Using bloc maybe occur reference cycle, but you can use weak
or unowned
to break it. Using a function as an observer is dangerous. We usually overlook these situations. Unlike bloc, it always reminds us to take care of the reference cycles, and we normally think functions are safe. So do not use functions unless you ensure the function doesn’t use any properties from self.