🚀 Learn how to build and use this package: https://www.swiftful-thinking.com/offers/REyNLwwH?coupon_code=LAUNCH3
Starter project for SwiftUI apps using VIPER architecture.
Details (Click to expand)
A starter project using VIPER/RIBs architecture in SwiftUI. You can learn how this architecture works and how to build this yourself in the SwiftUI Advanced Architecture course. This architecture can help your team build 10x faster, while writing testable code. The VIPER structure creates clear seperation of concerns and removes the guesswork for junior devs.
The data managers are erased to protocols and are dependency agnostic. The starter project is connected to Firebase (among other dependencies) but this can easily be swapped out.
Some pre-built features this project contains:
- Onboarding flow
- Tabbar flow
- Authentication logic
- User Management
- Paywall template
- In-app purchasing logic
- Routing logic
- Logging
- Analytics
- Crashlytics
- AB Testing
- Haptics
- Sound Effects
- Push Notifications
Details (Click to expand)
https://github.com/SwiftfulThinking/SwiftfulStarterProject.git
cd /pathtoproject/SwiftfulStarterProject
./rename_project.sh NewProjectName
If it doesn't work, you may need to make the script file executable by running
chmod +x rename_project.sh
- The new project should have all files already renamed.
- Manually add your Firebase plist files at /NewProjectName/Supporting Files/GoogleServicePLists
- Run the mock scheme to build without Firebase
- Update the bundle IDs for your organization
Details (Click to expand)
This architecture is taught in-depth in the SwiftUI Advanced Architecture course. Large groups, companies or educational institutions who decide to use this as training material can inquire about discounted rates at [email protected].
In this architecture, the SwiftUI framework is focused solely on building the UI layer of the application. Although Apple has provided data-centric Property Wrappers, such as @AppStorage or @Query, these have limited testability and ultimately restrict our ability to mock and develop the codebase with different environments.
We begin building a "Vanilla SwiftUI app". This is a basic SwiftUI implementation where all logic is held in the View. This is the easiest and most convenient way to build SwiftUI applications. Keeping all logic in the View, we can leverage SwiftUI's Environment and many Property Wrappers, such as @AppStorage. However, this leads to the "Massive-View-Controller" problem and severely limits testability.
We improve the architecture by introducing MVVM. In MVVM, we add an additional layer between the View and the dependencies (ie. the ViewModel). This allows us to move the business logic from the View into the ViewModel and then write tests for the ViewModel's logic. Although this is great for testability, it is less convenient for the developer, since we can no longer rely on SwiftUI's environment. Instead we need to inject the dependencies into each ViewModel ourselves.
If we further architect the application, we can decouple the routing from the View and move that logic into the ViewModel as well. To further improve testability of the ViewModel, we can abstract both the routing dependencies and the data dependencies to protocols. We can rename the ViewModel as Presenter, which now has a Router and an Interactor, completing the VIPER implementation.
When implemented well, VIPER is an improvement to MVVM architecture. In SwiftUI, both architectures run on the same foundation - an observable class that publishes updates back to the View. The main difference being that VIPER also includes the routing logic for the screen. You can think of the Presenter in the same way that you think of a ViewModel.
- View
- UI layer of the screen
- Interactor
- Data-related logic
- Presenter
- Business logic between the View and the Router/Interactor layers
- Entity
- A data model
- Router
- Screen routing logic
The project also incorporates a RIB pattern to create high-level modules across the application. The Starter Project has the entire project within 1 RIB (ie. CoreRouter, CoreInteractor, CoreBuilder), however, the application can be further broken into more RIBs as displayed in the SwiftUI Advanced Architecture course. Most teams will find it much faster to build with only 1 RIB.
This is a SwiftUI adaptation inspired by Uber's RIBs architecture.
- Router
- All routing methods for the module
- Interactor
- All data-related methods for the module
- Builder
- All screens within the module
The below image shows RIBs structure in an app with 3 RIBs.
Implementing VIPER + RIBs, brings a complete SwiftUI architecture that can adapt for any team.
- VIPER enables the business logic for each screen to be testable.
- RIBs enables us to modulate the codebase while reusing the interactor/router methods within each module.
The below diagram shows an application with 5 VIPER screens set within 1 RIB.
Thanks for reading! This starter project is provided for free from Swiftful Thinking. If you want to learn how to use this architecture and 10x your development speed, I highly suggest taking SwiftUI Advanced Architecture course!
The starter project includes the following dependencies, which can be easily removed or swapped as needed:
- Firebase
- SDWebImageSwiftUI
- SwiftfulAuthenticating
- SwiftfulAuthenticatingFirebase
- SwiftfulFirestore
- SwiftfulHaptics
- SwiftfulLogging
- SwiftfulLoggingCrashlytics
- SwiftfulLoggingMixpanel
- SwiftfulLoggingFirebaseAnalytics
- SwiftfulPurchasing
- SwiftfulPurchasingRevenueCat
- SwiftfulRouting
- SwiftfulSoundEffects
- SwiftfulUI
- SwiftfulUtilities