Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Introduction to VIPER Architecture

1,857 views

Published on

The base architecture of iOS is MVC (Model View Controller) which leads into known as Massive View Controller, where the View Controllers end up doing so many logic. It is easy to mix UI code and business logic together which is the wrong way to test the logic.

VIPER is one of a modern architecture made for this issue. It is based by Uncle Bob's Clean Architecture. It use the Separation of Concern principle which make the code cleaner and easy to maintenance.

Published in: Engineering
  • Hello! Who wants to chat with me? Nu photos with me here http://bit.ly/helenswee
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Thank you for sharing link. There are several examples about VIPER. I made this slide when I was reading https://objc.io. This is one of their repo: https://github.com/objcio/issue-13-viper-swift. I hope you can modify the classes and protocols based on your project's needs or code style. But the concept should stay the same. :)
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • For more advanced tips and helpful good practices on VIPER architecture, I recommend this post: https://www.ckl.io/blog/best-practices-viper-architecture (sample project included)
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Introduction to VIPER Architecture

  1. 1. Introduction to VIPER Architecture Hendy Christianto
  2. 2. Why VIPER? • MVC - Massive View Controller • What goes into View Controllers? • Data sources for Views (UITableViews) • Business Logic • Application Flows • Transition between view controller
  3. 3. What is VIPER? • Based on clean architecture to Uncle Bob’s clean architecture. • Basically a new architecture, introduced on 2014 • Used to resolve “Massive View Controller” • Using “Single Responsibility” as a principle
  4. 4. Architecture of VIPER
  5. 5. View • The View is passive • Waits for the Presenter to give content to display • Detect user interaction • The view is an abstract interface
  6. 6. View Cont’d @protocol SignInEmailView <NSObject> - (void)setEmailLabelText:(NSString *)email; - (void)setPasswordLabelText:(NSString *)password; @end #import <UIKit/UIKit.h> #import "SignInEmailView.h" @interface ViewController : UIViewController <SignInEmailView> @end only protocols, abstract interface implements SignInEmailView interface View Presenter setPasswordLabelText:
  7. 7. Presenter • Tells the view what to display • Handle events
  8. 8. Presenter Cont’d @implementation ViewController #pragma mark - #pragma mark View Interface - (void)setEmailLabelText:(NSString *)email { self.emailLabel.text = email; } - (void)setPasswordLabelText:(NSString *)password { self.passwordLabel.text = password; } - (void)setErrorMessage:(NSString *)error { self.errorLabel.text = error; } #pragma mark - #pragma mark IBAction - (IBAction)buttonLoginClicked:(id)sender { [self.presenter didLoginWithEmail:self.emailTextField.text password:self.passwordTextField.text]; } PresenterView buttonLoginClicked: didLoginWithEmail: password: Interactor signInWithEmail:password: @implementation SignInPresenter #pragma mark - #pragma mark Wireframe Update UI - (void)presentSignInEmailView { [self.view setPasswordLabelText:@"Password"]; [self.view setEmailLabelText:@"Email"]; } - (void)didLoginWithEmail:(NSString *)email password:(NSString *)password { [self.interactor signInWithEmail:email password:password]; } @end #import <Foundation/Foundation.h> #import "SignInEmailView.h" #import "SignInInteractorIO.h" @interface SignInPresenter : NSObject @property (nonatomic, weak) id <SignInEmailView> view; @property (nonatomic, strong) id <SignInInteractorInput> interactor; - (void)presentSignInEmailView; - (void)didLoginWithEmail:(NSString *)email password:(NSString *)password; @end
  9. 9. Interactor • Perform business logic • Carry out events that notified by presenter (input) • Produce output and notify back the presenter
  10. 10. Interactor Cont’d InteractorPresenter signInWithEmail:password: didSignInWithResponse: @implementation SignInPresenter #pragma mark - #pragma mark Wireframe Update UI - (void)presentSignInEmailView { [self.view setPasswordLabelText:@"Password"]; [self.view setEmailLabelText:@"Email"]; } - (void)didLoginWithEmail:(NSString *)email password:(NSString *)password { [self.interactor signInWithEmail:email password:password]; } #pragma mark - #pragma mark Interactor - (void)didSignInWithResponse:(NSDictionary *)response { NSError *error = response[@"error"]; if (error) { [self.view setErrorMessage:error.domain]; } else { [self.signInWireframe pushWelcomeView]; } } @interface SignInInteractor () @property (nonatomic, strong) SignInDataManager *dataManager; @end @implementation SignInInteractor - (void)signInWithEmail:(NSString *)email password:(NSString *)password { [self.dataManager userWithEmail:email password:password completion:^(User *user) { NSMutableDictionary *response = [NSMutableDictionary new]; if (user) { response[@"user"] = user; } else { response[@"error"] = [NSError errorWithDomain:@"User Not Found" code:404 userInfo:nil]; } [self.output didSignInWithResponse:response]; }]; } @end @interface SignInInteractor : NSObject <SignInInteractorInput> @property (nonatomic, weak) id <SignInInteractorOutput> output; @end @protocol SignInInteractorInput <NSObject> - (void)signInWithEmail:(NSString *)email password:(NSString *)password; @end @protocol SignInInteractorOutput <NSObject> - (void)didSignInWithResponse:(NSDictionary *)response; Data Manager userWithEmail:password:completion: completion:^(User *user)
  11. 11. Data Manager • Fetch data from database • Restructure data to model / entities • Store data
  12. 12. Data Manager Cont’d Data Manager Interactor @interface SignInInteractor () @property (nonatomic, strong) SignInDataManager *dataManager; @end @implementation SignInInteractor - (void)signInWithEmail:(NSString *)email password:(NSString *)password { [self.dataManager userWithEmail:email password:password completion:^(User *user) { NSMutableDictionary *response = [NSMutableDictionary new]; if (user) { response[@"user"] = user; } else { response[@"error"] = [NSError errorWithDomain:@"User Not Found" code:404 userInfo:nil]; } [self.output didSignInWithResponse:response]; }]; } @end Service userWithEmail:password:completion: @implementation SignInDataManager - (void)userWithEmail:(NSString *)email password:(NSString *)password completion:(void (^)(User *))completionBlock { NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(email == %@)", email]; [self.dataStore fetchEntriesWithPredicate:predicate sortDescriptors:@[] completionBlock:^(NSArray *results) { if (completionBlock) { if (results.count == 0) { completionBlock(nil); } else { completionBlock(results[0]); } } }]; } @end fetchEntriesWithPredicate:sortDescriptors:completionBlock results arrayrun completionBlock:
  13. 13. Service • Execute requests related to Entities / Models • Network/ API, Database (local)
  14. 14. Entities • Represent data • Passed between class
  15. 15. Entities Cont’d @interface User : NSManagedObject @property (nonatomic, strong) NSString *email; @property (nonatomic, strong) NSString *name; @end @implementation User @dynamic name; @dynamic email; @end
  16. 16. Wireframe • Initialize view controllers, Presenter, Interactor • Handles routing / navigation within Views
  17. 17. Wireframe Cont’d @class SignInPresenter; @class WelcomeWireframe; @interface SignInWireframe : RootWireframe @property (nonatomic, strong) WelcomeWireframe *welcomeWireframe; - (void)pushWelcomeView; - (void)presentSignInViewControllerOnWindow:(UIWindow *)window; @end static NSString *ViewControllerIdentifier = @"ViewController"; @interface SignInWireframe () @property (nonatomic, strong) SignInPresenter *presenter; @property (nonatomic, strong) SignInInteractor *interactor; @end @implementation SignInWireframe - (void)initializeClasses { self.presenter = [[SignInPresenter alloc] init]; self.interactor = [[SignInInteractor alloc] init]; self.presenter.interactor = self.interactor; self.interactor.output = self.presenter; } - (void)presentSignInViewControllerOnWindow:(UIWindow *)window { [self initializeClasses]; ViewController *signInVC = [self signInViewController]; signInVC.presenter = self.presenter; self.presenter.view = signInVC; [self createNavigationControllerWithRootView:signInVC]; window.rootViewController = self.navigationController; } - (void)pushWelcomeView { [self.welcomeWireframe pushWelcomeViewControllerOnNavigation:self.navigationController]; } - (ViewController *)signInViewController { UIStoryboard *storyboard = [self mainStoryboard]; ViewController *signInVC = [storyboard instantiateViewControllerWithIdentifier:ViewControllerIdentifier]; return signInVC; }
  18. 18. Benefits of Viper • Easy to iterate on • Collaboration-friendly • Separated concerns • Easy to test
  19. 19. Conclusion • Helps developer to be more explicit about separation of code • Single responsibility each class, easier to maintain • Neat Code!!
  20. 20. References • http://mutualmobile.github.io/blog/2013/12/04/viper- introduction/ • http://www.objc.io/issue-13/viper.html • https://medium.com/brigade-engineering/brigades- experience-using-an-mvc-alternative-36ef1601a41f • http://blog.8thlight.com/uncle-bob/2012/08/13/the-clean- architecture.html • iOS viper presentation - http://www.slideshare.net/ RajatDatta1/i-os-viper-presentation
  21. 21. DEMOS
  22. 22. Q&A

×