Skip to content
Go to file
This branch is 43 commits ahead, 1 commit behind rambler-digital-solutions:master.

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time


License MIT Pod version Build Status

NOTE: Base code is a fork of Rambler VIPER McFlurry

VIPER McFlurry is a modern framework for implementing VIPER architecture in iOS application. It offers several tools and components that help either start new projects with VIPER or move from MVC.




Key Features

  • The framework itself pushes you to implement a proper VIPER architecture,
  • It provides an extremely nice and easy way to implement intermodule data transfer,
  • Used in default Generamba template.


This example works only for Module with UIViewController as View. However, it's possible to use this approach even with UIView and UITableViewCell acting as View.

  • Create Module input protocol for target module inherited from RamblerViperModuleInput:
@protocol SomeModuleInput <RamblerViperModuleInput>

- (void)moduleConfigurationMethod;

  • Make Presenter of target module conform to this protocol.
  • Inject Presenter as moduleInput property of the view. You can skip this step if presenter is a view property with name "output".
  • Add Segue from source module ViewController to target module ViewController.
  • Inject Source ViewController into Source Router as property "transition handler".
  • In Router method call transition handler to open target module with configuration during segue.
[[self.transitionHandler openModuleUsingSegue:SegueIdentifier]
	thenChainUsingBlock:^id<RamblerViperModuleOutput>(id<SomeModuleInput> moduleInput) {
		[moduleInput moduleConfigurationMethod];
		return nil;

Working with Module output

  • Create Module output protocol for target module inherited from RamblerViperModuleOutput:
@protocol SomeModuleOutput <RamblerViperModuleOutput>

- (void)moduleConfigurationMethod;

  • Make source module presenter to conform to this protocol.
  • Add to target module presenter method:
- (void)setModuleOutput:(id<RamblerViperModuleOutput>)moduleOutput;
  • Return source module presenter from configuration block in router:
[[self.transitionHandler openModuleUsingSegue:SegueIdentifier]
	thenChainUsingBlock:^id<RamblerViperModuleOutput>(id<SomeModuleInput> moduleInput) {
		[moduleInput moduleConfigurationMethod];
		return sourceRouterPresenter; // Return of module output

Working with Module Factory

Module factory can be replaced with segues for most cases. Except you need to create complex module or nontrivial module instantiation logic.

  • Use RamblerViperModuleFactory object as module fabric with Typhoon.
  • Set definition Initializer to initWithViewControllerLoader:andViewControllerIdentifier:
    • First parameter is the object which loads the view controller, e.g. UIStoryboard or TyphoonNibLoader instance,
    • Second parameter is view controller's identifier, e.g. RestorationID or NibName of ViewController.
  • Typhoon will initialize module from ViewController.
  • Inject this Factory into router.
  • Call Transition Handler's method - openModuleUsingFactory:withTransitionBlock:.
  • Second block is place where transition from one to another viewController/transitionHandler should be performed:
    [[self.transitionHandler openModuleUsingFactory:self.betaModuleFactory
                                withTransitionBlock:^(id <RamblerViperModuleTransitionHandlerProtocol> sourceModuleTransitionHandler,
                                        id <RamblerViperModuleTransitionHandlerProtocol> destinationModuleTransitionHandler) {

                                    UIViewController *sourceViewController = (id) sourceModuleTransitionHandler;
                                    UIViewController *destinationViewController = (id) destinationModuleTransitionHandler;

                                    [sourceViewController.navigationController pushViewController:destinationViewController

                                }] thenChainUsingBlock:^id<RamblerViperModuleOutput>(id<RamblerModuleBetaInput> moduleInput) {
                                   [moduleInput configureWithExampleString:exampleString];
                                   return nil;
transitionHandler.openModule!(usingFactory: SomeModuleConfigurator()) { (sourceModuleTransitionHandler, destinationModuleTransitionHandler) in

            let sourceViewController = sourceModuleTransitionHandler as! UIViewController
            let destinationViewController = destinationModuleTransitionHandler as! UIViewController

            sourceViewController.present(destinationViewController, animated: true, completion: nil)

        }.thenChain { (moduleInput) -> ViperModuleOutput? in
            (moduleInput as! SomeModuleInput).configure()
            return nil // or self.calleeOutput
  • In example above one module is pushed to navigation stack of another module.
  • Modules are linked with intermodule data transfer block.
Passthrough dismiss

For example, you have present module A, then present module B from A. Your task requires dismiss B and A at the same time directly to parent of A. In this case you can set self.transitionHandler.skipOnDismiss = true of A module, as result, when B call closeCurrentModule, then B and A will be dismissed together, and presenter of B will be notified via moduleDidSkipOnDismiss (if implemented).


Add to podfile

pod "ViperMcFlurryX"





Original code from Rambler&Co team:


As tasty as McFlurry is




No packages published
You can’t perform that action at this time.