When designing an app, you often have to present different views depending on the state. UIViewController containment is a good solution to reuse your view code and storyboards but it can become tedious to manage their insertion and removal, execute the transitions correctly and do the memory housekeeping. This is where MultiplexerController can help by creating a container that present its content as a function of the state.
- It calls
addChild
,removeChild
and all the callbacks needed - Handles the view insertion and removal
- Presents a nice fade if you want it
- Deals with the memory as it should
- Is bit sized with less than 200 lines so you can precisely check what it does
- iOS 10.0+
- Swift 4.2+
To integrate MultiplexerController into your Xcode project using CocoaPods, specify it in your Podfile
:
pod 'MultiplexerController', '~> 1.0.0'
To integrate MultiplexerController into your Xcode project using Carthage, specify it in your Cartfile
:
github "mobiten/MultiplexerController" "1.0.0"
A common usage of this library is the presentation of a loading screen and error states. We will use this enum for the following example:
enum State {
case loading
case loaded(WeatherForecast)
case error(Error)
}
First, create a MultiplexerController with an initial state. Then, provide it with a DataSource, it can be self or any other class implementing the MultiplexerControllerDataSource protocol.
let multiplexer = MultiplexerController(initialState: State.loading)
multiplexer.setDataSource(self)
Second, implement the protocol in your data source.
extension HomeController: MultiplexerControllerDataSource {
func controller(for controller: MultiplexerController<State>, inState state: State) -> UIViewController {
switch state {
case .loading:
return LoadingController()
case .error(let error):
return ErrorController(error)
case .loaded(let forecast):
return WeatherForecastController(forecast)
}
}
}
Third, change the state when you need it!
func didFetch(forecast: WeatherForecast) {
multiplexer.set(.loaded(forecast), animated: true)
}
Yes! and it is located in this repo.
When possible, you should always prefer composition over inheritance. If you want to use MultiplexerController, embed it in another container or just directly push it to your navigation stack.
By forcing you to use the same type (enum is highly recommended) you always know what to expect. As a side effect, if you use an exhaustive switch statement, you will get a nice compiler error when you add a new case to your possible state, reminding you to handle it gracefully in the app.