Hi guys, my name is Steve. Now I’m a platform engineer at VinID which is one of largest enterprise in Vietnam. We’re applying the RIBs architect design from Uber. I greatly appreciate this architect design because it was born for super-app or platform mobile system. It is a recommendation to take a look about RIBs on Github before reading this article.
While working with RIBs, one of pain points we often encounter is: “Leak memory”. Leak memory may happen everywhere & whenever we make some mistakes. Uber already provided a useful tool named “Leak Detector” to poke us when a leak happens. Sometime, there’re some special leaks, actually they aren’t kind of memory leak, it maybe called “logic leaks”, therefore tools or even systems don’t think they’re leaks, it is a reason why they can escape the “Leak Detector” safely. Today, I’m going to tell you one kind of “logic leaks” and how to avoid them.
In RIBs architect design, each business will be described as a RIB node, if a business needs another business for working, its RIB (parent) will attach a new RIB (child). After finishing, the RIB (parent) proactively detaches its children. Normally, a working mobile system will look like a RIB-tree:
This strategy helps us to isolates each business by each other, our businesses will be easier for maintenance & scalable. Take a deep look into the attach/detach process in RIBs. (Again, if you’re unfamiliar with RIBs, it’s recommendation to take a tour at Uber RIBs homepage on Github).
There’re many components in a RIB (Router, Interactor, Builder, Presenter, View, Component, Dependency, …). In this article, I only mention about 2 components: Interactor & View. When the parent RIB attaches a child RIB, they make relationships between their components.
When a user take an action on child View to finish, we need to detach the child RIB from its parent:
1. Child View sends an event to its interactor.
2. Child interactor sends an event to its parent Interactor.
3. Parent Interactor will send an event to its Router to start detaching the child RIB
In RIBs architect, Router component is responsible for routing/navigation children RIB nodes. This flow can be described as a diagram bellow:
If everything work well, there aren’t leaks here. In some corner cases, user may dismiss the View without follow the detaching flow. It means the child View will be dismissed but the (1) event wouldn’t be sent. Then user sees the parent View but the child RIB will not be detached! It is a kind of “logic leak” I’ve mentioned before.
Now we understand what does “logic leak” mean. Our iOS team encountered this leak when we upgrade to iOS 13. Apple has introduced a new style for modal presentation that supports a new way to dismiss a view controller: swipe down. You can read this article: View Controller Presentation Changes in iOS 13 from Geoff Hackworth for more information.
It is a nightmare with us because Apple forces that style as default but we aren’t ready to handle that dismissal, by the result, all RIB which have been attached as modal presentation are leaked when user swipe down to dismiss. The leaked RIBs still be allocated in memory then it is a memory leak as well. To resolve that issue, we have to handle the new dismissal way to make sure the (1) event must be sent immediately while user swipes down. That’s all!
In the Uber RIBs architect design, please make sure that we always dismiss a View correctly (by RIB detaching process instead of by itself) to avoid any accidental “logic leak”.
In the future, if I find a new kind of “logic leak”, I’ll post it to my medium soon. If you’re interesting about this article, don’t hesitate to follow me :D