- Application – contains app’s entry point files(AppDelegate, SceneDelegate), app configurations(dev, stg, prod) and
- App entry points (AppDelegate, SceneDelegate)
- AppContainer – container/builder for app services
- App configuraion
- Environment type (dev, stg, prod)
- Constants (special keys/identifiers)
- Models – response, database, domain entities
- Services – Independent services and managers
- Coordinators – app navigation control services
- Base – Base classes for app’s modules
- Extensions – Extensions for Foundation, UIKit, Combine, other classes/structs
- Helpers – Independent and reusable tools
- Views – Reusable views(which can be used twice or more times)
- Presentation – all modules in the app (can be grouped by flow)
- Resources – assets, colors, fonts, strings resources
Each module has 4 main components(can be more if you need to split giant logic in some of them):
Which are connected with controller though the bindings. In this case case controller acts as a connector between View and ViewModel.
- View is independent component.
- Each View has its own action publisher where you should notify subscribers(ex. ViewController) about user interaction inside its view.
- Action enum, publisher and subject will be generated automatically with providing template.
- (Optional) I prefer building UI from the code, but you can use Xib with IB.
- ViewModel is independent component.
- Each ViewModel has its own transition publisher where you should notify subscribers(ex. Coordinator) when you should go forward or backward in your flow.
- If ViewModel need some services or parameters, the should be injected through the initializer.
- Transion publisher and subject will be generated automatically with providing template.
- (Optional) I prefer storing temporary data in ViewModel directly, but you can create Model component and move it there.
- ViewController holds strong reference to View and ViewModel(BaseViewController contains ViewModel property as a generic type of “ViewModel”).
- ViewController listen to View’s action publisher and pass it to ViewModel.
- ViewController listen to ViewModel publishers and pass its data to View or interact by itself on its signals.
- Builder constructs a Module
- It creates needed components with injecting needed services and parameters and wrap it into “Module” type – which is just container with 2 generic types(controller and transition, image below)
- Builder also generates automatically with included template
- When app starts it builds an App Coordinator and starts one of the flows(run child coordinator)
- When its flow(child coordinator) will send finish signal througn the “didFinishPublisher”, parent coordinator can move its own flow or run another coordinator.
- Each coordinator initializes with UINavigationController and AppContainer and has “start” method
- “start” method build first(root) module for its coordinator
- Each methods in the coordinator should create a module(using Builder) pass container and other parameters if needed into it, subscribe to its transition publisher for running next modules or finishing the flow
- Application folder contains xcconfig files for managing different environments(contains type of environment, app name and bundleId)
- When AppConfiguration initializes it retrives environment type and other info from Info.plist by key
- Inside AppEvironment enum you should specify differences between your environments(ex. baseURL, apiToken, …)
- For running app with needed environment type – just select needed scheme