RxSwift MVVM Architecture Pattern
Article Summary
Martin Moizard from BlaBlaCar reveals a critical MVVM pitfall that breaks when you switch from simple views to UITableViews. The culprit? How you feed inputs to your ViewModels.
After a year of using RxSwift with MVVM at BlaBlaCar, the team discovered their initial approach to ViewModel inputs had a fatal flaw. Views that lazily load content (like UITableViews) couldn't provide all inputs synchronously, breaking the entire pattern. This article walks through two approaches to solving this architectural challenge.
Key Takeaways
- First approach uses transform functions but fails with lazy loaded views
- Subjects bridge imperative and functional worlds while keeping ViewModels testable
- Private Subjects prevent ViewModel hacking while maintaining clean public contracts
- Both patterns coexist: use transform for simple views, Subjects for complex ones
ViewModels need flexible input mechanisms to work with any view type, and strategic use of private Subjects solves this without sacrificing testability or clean architecture.
About This Article
BlaBlaCar's RxSwift MVVM pattern expected all ViewModel inputs to be available at once, but UITableView loads content lazily. This mismatch broke the transform function approach since inputs couldn't be gathered simultaneously.
Martin Moizard's team used private Subjects to bridge the gap between imperative and functional Rx code. Views only see public input and output properties, while the transformation logic stays intact underneath.
This approach let ViewModels work with any View type, whether a simple UIViewController or a complex UITableView. The code remained testable and encapsulation prevented Views from directly manipulating ViewModels.