{"id":2644,"date":"2016-04-28T19:11:58","date_gmt":"2016-04-28T19:11:58","guid":{"rendered":"http:\/\/www.ckl.io\/?p=2644"},"modified":"2026-08-15T08:45:44","modified_gmt":"2026-08-15T08:45:44","slug":"ios-project-architecture-using-viper","status":"publish","type":"post","link":"https:\/\/cheesecakelabs.com\/blog\/ios-project-architecture-using-viper\/","title":{"rendered":"iOS Project Architecture: Using VIPER"},"content":{"rendered":"\n<p>When developing an iOS app, it&#8217;s important to think about what iOS project architecture you should use. Most developers use the pattern <a href=\"https:\/\/developer.apple.com\/library\/ios\/documentation\/General\/Conceptual\/DevPedia-CocoaCore\/MVC.html\" target=\"_blank\" rel=\"noreferrer noopener\">suggested by Apple<\/a>: the so-called MVC (Model-View-Controller) architecture. However, as well-established as it is, the MVC has its flaws.<\/p>\n\n\n\n<p>For one, because of its simplicity, it leads even the most experienced engineers to put any code that doesn&#8217;t belong to a View nor to a Model in the Controller&#8217;s logic \u2013 generating huge chunks of code in the controller and really compact views and models.<\/p>\n\n\n\n<p>In this post, we&#8217;ll present VIPER, one of the trending alternatives to MVC that might help you overcome its limitations while keeping your code modular and well-organized, improving your <a href=\"https:\/\/cheesecakelabs.com\/services\/\" target=\"_blank\" rel=\"noreferrer noopener\">development<\/a> process.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. What is VIPER?<\/h2>\n\n\n\n<p>VIPER is a backronym for View, Interactor, Presenter, Entity and Router. It&#8217;s basically an approach that implements the <a href=\"https:\/\/drive.google.com\/a\/ckl.io\/file\/d\/0ByOwmqah_nuGNHEtcU5OekdDMkk\/view\" target=\"_blank\" rel=\"noreferrer noopener\">Single Responsibility Principle<\/a> to create a cleaner and more modular structure for your iOS project. The idea behind this pattern is to isolate your app&#8217;s dependencies, balancing the delegation of responsibilities among the entities. This is achieved by using the following architecture:<\/p>\n\n\n\n<p>&nbsp;<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" width=\"2432\" height=\"1156\" src=\"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2016\/04\/Viper-Module.png\" alt=\"Viper Module\" class=\"wp-image-2680\" srcset=\"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2016\/04\/Viper-Module.png 2432w, https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2016\/04\/Viper-Module-768x365.png 768w\" sizes=\"(max-width: 2432px) 100vw, 2432px\" \/><\/figure>\n<\/div>\n\n\n<p>The diagram above illustrates the VIPER architecture, in which each block corresponds to an object with specific tasks, inputs and outputs. Think of&nbsp;these blocks as workers in an assembly line: once the worker completes its job on an object, the object is passed along to the next worker, until the product is finished.<\/p>\n\n\n\n<p>The connections between the blocks represent the relationship between the objects, and what kind of information they transmit to each other. The communication&nbsp;from one entity to another is&nbsp;given through protocols, which we&#8217;ll explain further in this post.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. What are the parts of the VIPER iOS project architecture?<\/h2>\n\n\n\n<p>The VIPER iOS project architecture has five parts: View, Interactor, Presenter, Entity and Router. Each one owns a specific set of responsibilities, and they pass work to each other through protocols. Knowing what every part does, and where its responsibility ends, is the key to using the pattern well. To see how they fit together, we&#8217;ll develop a basic application (code also available on <a href=\"https:\/\/github.com\/pedrohperalta\/Articles-iOS-VIPER\">GitHub<\/a>) that fetches a list of articles from a REST API and displays them on the user&#8217;s screen.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2.1. View<\/h3>\n\n\n\n<p>The VIPER View in an iOS application is a UIViewController that contains a sub view, which can be either implemented programmatically or using the Interface Builder (IB). Its sole responsibility is to display what the <strong>Presenter<\/strong> tells it to, and handle the user interactions with the screen.<\/p>\n\n\n\n<p>When the user triggers any event that requires processing, the <strong>View<\/strong> simply delegates it to the <strong>Presenter<\/strong> and waits for a response telling it what should be displayed next.<\/p>\n\n\n\n<p>This is how the&nbsp;<strong>View<\/strong>&nbsp;for our Article Visualization app&nbsp;would look in Swift:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">\n\/*\n * Protocol that defines the view input methods.\n *\/\nprotocol ArticlesViewInterface: class {\n    func showArticlesData(articles: &#91;Article])\n    func showNoContentScreen()\n}\n\n\/*\n * A view responsible for displaying a list\n * of articles fetched from some source.\n *\/\nclass ArticlesViewController : UIViewController, ArticlesViewInterface\n{\n    \/\/ Reference to the Presenter's interface.\n    var presenter: ArticlesModuleInterface!\n\n    \/*\n     * Once the view is loaded, it sends a command\n     * to the presenter asking it to update the UI.\n     *\/\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        self.presenter.updateView()\n    }\n\n    \/\/ MARK: ArticlesViewInterface\n\n    func showArticlesData(articles: &#91;Article]) {\n        self.articles = articles\n        self.tableView.reloadData()\n    }\n\n    func showNoContentScreen() {\n        \/\/ Show custom empty screen.\n    }\n}\n<\/code><\/span><\/pre>\n\n\n<h3 class=\"wp-block-heading\">2.2. Presenter<\/h3>\n\n\n\n<p>The <strong>Presenter<\/strong> works like a bridge between the main parts of a VIPER module. On&nbsp;one hand, it receives input events coming from the View and reacts to them by requesting data from the Interactor. On&nbsp;the other hand, it receives the data structures coming from the <strong>Interactor<\/strong>, applies <span style=\"text-decoration: underline\">view<\/span> logic over this data to prepare the content, and finally tells the <strong>View<\/strong> what to display.<\/p>\n\n\n\n<p>Here&#8217;s an example of a <strong>Presenter<\/strong> for our Article Visualization app:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">\n\/*\n * Protocol that defines the commands sent from the View to the Presenter.\n *\/\nprotocol ArticlesModuleInterface: class {\n    func updateView()\n    func showDetailsForArticle(article: Article)\n}\n\n\n\/*\n * Protocol that defines the commands sent from the Interactor to the Presenter.\n *\/\nprotocol ArticlesInteractorOutput: class {\n    func articlesFetched(articles: &#91;Article])\n}\n\n\n\/*\n * The Presenter is also responsible for connecting\n * the other objects inside a VIPER module.\n *\/\nclass ArticlesPresenter : ArticlesModuleInterface, ArticlesInteractorOutput\n{\n    \/\/ Reference to the View (weak to avoid retain cycle).\n    weak var view: ArticlesViewInterface!\n\n    \/\/ Reference to the Interactor's interface.\n    var interactor: ArticlesInteractorInput!\n\n    \/\/ Reference to the Router\n    var wireframe: ArticlesWireframe!\n\n\n    \/\/ MARK: ArticlesModuleInterface\n\n    func updateView() {\n        self.interactor.fetchArticles()\n    }\n\n    func showDetailsForArticle(article: Article) {\n        self.wireframe.presentDetailsInterfaceForArticle(article)\n    }\n\n    \/\/ MARK: ArticlesInteractorOutput\n\n    func articlesFetched(articles: &#91;Article]) {\n        if articles.count &gt; 0 {\n            self.articles = articles\n            self.view.showArticlesData(articles)\n        } else {\n            self.view.showNoContentScreen()\n        }\n    }\n}\n<\/code><\/span><\/pre>\n\n\n<h3 class=\"wp-block-heading\">2.3. Interactor<\/h3>\n\n\n\n<p>We can think about this object as a collection of use cases inside of a specific module. The <strong>Interactor<\/strong> contains all the business logic related to the entities and should be completely independent of the<strong> user interface (UI).<\/strong><\/p>\n\n\n\n<p>In our Article Visualization&nbsp;app, one use case example is to fetch the list of articles from the server. It&#8217;s the <strong>Interactor<\/strong>&#8216;s responsibility to make the requests, handle the responses and convert them to an <strong>Entity<\/strong> which, in this case, is an Article object.<\/p>\n\n\n\n<p>Once the <strong>Interactor<\/strong> finishes running&nbsp;some task, it notifies the <strong>Presenter<\/strong> about the result obtained. One important thing to keep in mind is that the data sent to&nbsp;the&nbsp;<strong>Presenter<\/strong> should not implement&nbsp;any business logic, so the data provided by the <strong>Interactor<\/strong> should be clean and ready to use.<\/p>\n\n\n\n<p>In our Article Visualization app, the <strong>Interactor&nbsp;<\/strong>would be responsible for fetching the articles from an API:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">\n\/*\n * Protocol that defines the Interactor's use case.\n *\/\nprotocol ArticlesInteractorInput: class {\n    func fetchArticles()\n}\n\n\n\/*\n * The Interactor responsible for implementing\n * the business logic of the module.\n *\/\nclass ArticlesInteractor : ArticlesInteractorInput\n{\n    \/\/ Url to the desired API.\n    let url = \"https:\/\/www.myendpoint.com\"\n\n    \/\/ Reference to the Presenter's output interface.\n    weak var output: ArticlesInteractorOutput!\n\n\n    \/\/ MARK: ArticlesInteractorInput\n\n    func fetchArticles() {\n        Alamofire.request(.GET, url).responseArray { (response: Response) in\n            let articlesArray = response.result.value\n            self.output.articlesFetched(articlesArray!)\n        }\n    }\n}\n<\/code><\/span><\/pre>\n\n\n<h3 class=\"wp-block-heading\">2.4. Entity<\/h3>\n\n\n\n<p>The <strong>Entity<\/strong> is probably the simplest element inside a VIPER structure. It encapsulates different types of data, and usually is treated as a payload among the other VIPER components. One important thing to notice is that the <strong>Entity<\/strong> is different from the Data Access Layer, which should be handled by the <strong>Interactor<\/strong>.<\/p>\n\n\n\n<p>In our Article Visualization app, the Article class would be an example of an <strong>Entity<\/strong>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Article<\/span>\n<\/span>{\n    <span class=\"hljs-keyword\">var<\/span> date: <span class=\"hljs-built_in\">String<\/span>?\n    <span class=\"hljs-keyword\">var<\/span> title: <span class=\"hljs-built_in\">String<\/span>?\n    <span class=\"hljs-keyword\">var<\/span> website: <span class=\"hljs-built_in\">String<\/span>?\n    <span class=\"hljs-keyword\">var<\/span> authors: <span class=\"hljs-built_in\">String<\/span>?\n    <span class=\"hljs-keyword\">var<\/span> content: <span class=\"hljs-built_in\">String<\/span>?\n    <span class=\"hljs-keyword\">var<\/span> imageUrl: <span class=\"hljs-built_in\">String<\/span>?\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">2.5. Router<\/h3>\n\n\n\n<p>The last and perhaps most peculiar element in the VIPER architecture is the <strong>Router<\/strong>, which is responsible for the navigation logic between modules, and how they should happen (e.g. defining an animation for presenting a screen, or how the transition between two screens should be done). It receives input commands from the <strong>Presenters<\/strong> to say what screen it should route to. Also, the <strong>Router<\/strong> should be responsible for passing data from one screen to the other.<\/p>\n\n\n\n<p>The <strong>Router<\/strong>&nbsp;should implement a protocol that defines all the navigation possibilities for a specific module. That&#8217;s a good practice because it enables a quick overview of all the paths an app can take by&nbsp;only looking at&nbsp;a <strong>Router<\/strong>&#8216;s protocol.<\/p>\n\n\n\n<p>Because of a limitation from the iOS framework, only <strong>ViewControllers<\/strong> can perform a transition between screens, so a <strong>Router<\/strong> must contain a reference to the module&#8217;s controller, or any of its children.<\/p>\n\n\n\n<p>Here&#8217;s how our router would look in our Article Visualization app (note that the <strong>Router<\/strong> is widely referred to as <strong>Wireframe<\/strong>).<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">\n\/*\n * Protocol that defines the possible routes from the Articles module.\n *\/\nprotocol ArticlesWireframeInput {\n    func presentDetailsInterfaceForArticle(article: Article)\n}\n\n\n\/*\n * The Router responsible for navigation between modules.\n *\/\nclass ArticlesWireframe : NSObject, ArticlesWireframeInput\n{\n    \/\/ Reference to the ViewController (weak to avoid retain cycle).\n    weak var articlesViewController: ArticlesViewController!\n\n    \/\/ Reference to the Router of the next VIPER module.\n    var detailsWireframe: DetailsWireframe!\n\n\n    \/\/ MARK: ArticlesWireframeInput\n\n    func presentDetailsInterfaceForArticle(article: Article) {\n        \/\/ Create the Router for the upcoming module.\n        self.detailsWireframe = DetailsWireframe()\n\n        \/\/ Sends the article data to the next module's Presenter.\n        self.sendArticleToDetailsPresenter(self.detailsWireframe.detailsPresenter, article: article)\n\n        \/\/ Presents the next View.\n        self.detailsWireframe.presentArticleDetailsInterfaceFromViewController(self.articlesViewController)\n    }\n\n\n    \/\/ MARK: Private\n\n    private func sendArticleToDetailsPresenter(detailsPresenter: DetailsPresenter, article: Article) {\n        detailsPresenter.article = article\n    }\n}\n<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\">3.&nbsp;When should you use VIPER?<\/h2>\n\n\n\n<p>When creating a project&nbsp;that has the potential to evolve, it&#8217;s important to think of a structure that will scale well and enable&nbsp;many developers to simultaneously work&nbsp;on it as seamlessly as possible \u2013 and the&nbsp;MVC structure might not be enough to keep your project sufficiently organized.<\/p>\n\n\n\n<p>It&#8217;s really common for developers to find themselves&nbsp;debugging&nbsp;a huge class, like trying to find a needle in a haystack. With the loose coupling between the objects that&nbsp;VIPER proposes, you&#8217;ll notice that:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>It&#8217;s easier to track issues via crash reports (due to the Single Responsibility Principle)<\/li>\n\n\n\n<li>Adding new features is easier<\/li>\n\n\n\n<li>The source code will be cleaner, more compact and reusable<\/li>\n\n\n\n<li>There are fewer conflicts with the rest of the development team<\/li>\n\n\n\n<li>It&#8217;s easier to write automated tests (!), since your UI logic is separated from the business logic.<\/li>\n<\/ul>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><strong>Read more: <\/strong><a href=\"https:\/\/cheesecakelabs.com\/blog\/ai-for-software-development\/\" id=\"12514\" target=\"_blank\" rel=\"noreferrer noopener\">AI for Software Development: Best Practices and Tools<\/a><\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">4.&nbsp;When should you NOT use VIPER?<\/h2>\n\n\n\n<p>As with every problem&nbsp;you&#8217;re trying to solve, you should turn to the tool that best suits your needs. Due to the number of elements involved, this architecture&nbsp;causes overhead when starting a new project (though it largely pays off&nbsp;in the long run), so VIPER can&nbsp;be overkill for small projects that do not intend to scale.<\/p>\n\n\n\n<p>If the team isn&#8217;t completely aligned with maintaining the VIPER&nbsp;structure, you&#8217;ll end up with an MVC-VIPER mix that can cause headaches \u2013 so make sure the team is completely in&nbsp;sync before moving forward with VIPER.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">5. Wrapping up<\/h2>\n\n\n\n<p>VIPER is a really cool iOS project architecture pattern&nbsp;among others, like MVP&nbsp;and&nbsp;MVVM. If you&#8217;re curious to know more about the VIPER architecture,&nbsp;you can check out the <a href=\"https:\/\/github.com\/pedrohperalta\/Articles-iOS-VIPER\" target=\"_blank\" rel=\"noopener\">repository<\/a> with the full implementation of the&nbsp;example used in this post. Feel&nbsp;free to contribute with issues and pull requests!<\/p>\n\n\n\n<p><strong>What is your favorite iOS project architecture? <\/strong>Please share your opinion in the comments!<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/cheesecakelabs.com\/services\/\" target=\"_blank\" rel=\" noreferrer noopener\"><img decoding=\"async\" width=\"1200\" height=\"409\" src=\"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2023\/06\/legacy-app-ckl-1200x409.jpg\" alt=\"legacy-app-ckl | | Cheesecake Labs\" class=\"wp-image-13491\" srcset=\"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2023\/06\/legacy-app-ckl-1200x409.jpg 1200w, https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2023\/06\/legacy-app-ckl-600x205.jpg 600w, https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2023\/06\/legacy-app-ckl-768x262.jpg 768w, https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2023\/06\/legacy-app-ckl-1536x524.jpg 1536w, https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2023\/06\/legacy-app-ckl-760x259.jpg 760w, https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2023\/06\/legacy-app-ckl.jpg 1920w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/a><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>When developing an iOS app, it&#8217;s important to think about what iOS project architecture you should use. Most developers use the pattern suggested by Apple: the so-called MVC (Model-View-Controller) architecture. However, as well-established as it is, the MVC has its flaws. For one, because of its simplicity, it leads even the most experienced engineers to [&hellip;]<\/p>\n","protected":false},"author":65,"featured_media":2938,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_yoast_wpseo_focuskw":"ios project architecture","_yoast_wpseo_title":"iOS Project Architecture: VIPER Explained in Swift","_yoast_wpseo_metadesc":"VIPER is an iOS project architecture built on View, Interactor, Presenter, Entity and Router. See how each part works in Swift, and when it's overkill.","_yoast_wpseo_meta-robots-noindex":"","_yoast_wpseo_canonical":"","footnotes":"","ckl_wpml_lang":"","ckl_wpml_source_id":0,"ckl_wpml_status":""},"categories":[1425,432],"tags":[287,123],"class_list":["post-2644","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-product-engineering","category-engineering","tag-tag-code","tag-tag-ios-development"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.1.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>iOS Project Architecture: VIPER Explained in Swift<\/title>\n<meta name=\"description\" content=\"VIPER is an iOS project architecture built on View, Interactor, Presenter, Entity and Router. See how each part works in Swift, and when it&#039;s overkill.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/cheesecakelabs.com\/blog\/ios-project-architecture-using-viper\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"iOS Project Architecture: VIPER Explained in Swift\" \/>\n<meta property=\"og:description\" content=\"VIPER is an iOS project architecture built on View, Interactor, Presenter, Entity and Router. See how each part works in Swift, and when it&#039;s overkill.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cheesecakelabs.com\/blog\/ios-project-architecture-using-viper\/\" \/>\n<meta property=\"og:site_name\" content=\"Cheesecake Labs\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/cheesecakelabs\" \/>\n<meta property=\"article:published_time\" content=\"2016-04-28T19:11:58+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-08-15T08:45:44+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2016\/04\/viper_architecture.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"2076\" \/>\n\t<meta property=\"og:image:height\" content=\"720\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Cheesecake Labs\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@cheesecakelabs\" \/>\n<meta name=\"twitter:site\" content=\"@cheesecakelabs\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/cheesecakelabs.com\/blog\/ios-project-architecture-using-viper\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/cheesecakelabs.com\/blog\/ios-project-architecture-using-viper\/\"},\"author\":{\"name\":\"Pedro Henrique Peralta\"},\"headline\":\"iOS Project Architecture: Using VIPER\",\"datePublished\":\"2016-04-28T19:11:58+00:00\",\"dateModified\":\"2026-08-15T08:45:44+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cheesecakelabs.com\/blog\/ios-project-architecture-using-viper\/\"},\"wordCount\":1288,\"commentCount\":4,\"publisher\":{\"@id\":\"https:\/\/cheesecakelabs.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/cheesecakelabs.com\/blog\/ios-project-architecture-using-viper\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2016\/04\/viper_architecture.jpg\",\"keywords\":[\"code\",\"iOS development\"],\"articleSection\":[\"Product Engineering\",\"Engineering\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/cheesecakelabs.com\/blog\/ios-project-architecture-using-viper\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cheesecakelabs.com\/blog\/ios-project-architecture-using-viper\/\",\"url\":\"https:\/\/cheesecakelabs.com\/blog\/ios-project-architecture-using-viper\/\",\"name\":\"iOS Project Architecture: VIPER Explained in Swift\",\"isPartOf\":{\"@id\":\"https:\/\/cheesecakelabs.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cheesecakelabs.com\/blog\/ios-project-architecture-using-viper\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cheesecakelabs.com\/blog\/ios-project-architecture-using-viper\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2016\/04\/viper_architecture.jpg\",\"datePublished\":\"2016-04-28T19:11:58+00:00\",\"dateModified\":\"2026-08-15T08:45:44+00:00\",\"description\":\"VIPER is an iOS project architecture built on View, Interactor, Presenter, Entity and Router. See how each part works in Swift, and when it's overkill.\",\"breadcrumb\":{\"@id\":\"https:\/\/cheesecakelabs.com\/blog\/ios-project-architecture-using-viper\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cheesecakelabs.com\/blog\/ios-project-architecture-using-viper\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cheesecakelabs.com\/blog\/ios-project-architecture-using-viper\/#primaryimage\",\"url\":\"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2016\/04\/viper_architecture.jpg\",\"contentUrl\":\"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2016\/04\/viper_architecture.jpg\",\"width\":2076,\"height\":720,\"caption\":\"viper_architecture | | Cheesecake Labs\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cheesecakelabs.com\/blog\/ios-project-architecture-using-viper\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cheesecakelabs.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"iOS Project Architecture: Using VIPER\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/cheesecakelabs.com\/blog\/#website\",\"url\":\"https:\/\/cheesecakelabs.com\/blog\/\",\"name\":\"Cheesecake Labs\",\"description\":\"AI Implementation, Data and Product Engineering\",\"publisher\":{\"@id\":\"https:\/\/cheesecakelabs.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/cheesecakelabs.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/cheesecakelabs.com\/blog\/#organization\",\"name\":\"Cheesecake Labs\",\"alternateName\":\"Cheesecake Labs Inc\",\"url\":\"https:\/\/cheesecakelabs.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/cheesecakelabs.com\/#logo\",\"url\":\"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2022\/06\/cheesecake-labs-1.png\",\"contentUrl\":\"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2022\/06\/cheesecake-labs-1.png\",\"caption\":\"Cheesecake Labs\",\"inLanguage\":\"en\"},\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/cheesecakelabs.com\/#primary-image\",\"url\":\"https:\/\/ckl-website-v4-strapi-prod.s3.us-east-2.amazonaws.com\/ai_software_development_company_83fb512983.webp\",\"contentUrl\":\"https:\/\/ckl-website-v4-strapi-prod.s3.us-east-2.amazonaws.com\/ai_software_development_company_83fb512983.webp\",\"width\":1920,\"height\":1080,\"caption\":\"Cheesecake Labs \u2014 AI, Data & Blockchain software development services\",\"inLanguage\":\"en\"},\"sameAs\":[\"https:\/\/www.facebook.com\/cheesecakelabs\",\"https:\/\/x.com\/cheesecakelabs\",\"https:\/\/www.instagram.com\/cheesecakelabs\/\",\"https:\/\/www.linkedin.com\/company\/cheesecake-labs\/\",\"https:\/\/www.youtube.com\/channel\/UCdGEQ5AHJcmIlaOaI5fGGVA\",\"https:\/\/clutch.co\/profile\/cheesecake-labs\",\"https:\/\/www.behance.net\/cheesecakelabs\",\"https:\/\/dribbble.com\/cheesecakelabs\",\"https:\/\/www.designrush.com\/agency\/profile\/cheesecake-labs\",\"https:\/\/www.g2.com\/products\/cheesecake-labs\/reviews\"],\"description\":\"Cheesecake Labs is a software development studio that designs and builds custom digital products \u2014 web, mobile, and platforms \u2014 combining product design and high-performance engineering.\",\"foundingDate\":\"2013\"},{\"@type\":\"Person\",\"name\":\"Pedro Henrique Peralta\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cheesecakelabs.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2017\/09\/pedro-300x300.jpg\",\"contentUrl\":\"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2017\/09\/pedro-300x300.jpg\",\"caption\":\"Pedro Henrique Peralta\"},\"description\":\"10 years of experience in Marketing and Sales in the Technology sector. My main purpose is help, support and structure efficient operations and also develop independent and multidisciplinary teams.\",\"url\":\"https:\/\/cheesecakelabs.com\/blog\/autor\/pedro-2\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"iOS Project Architecture: VIPER Explained in Swift","description":"VIPER is an iOS project architecture built on View, Interactor, Presenter, Entity and Router. See how each part works in Swift, and when it's overkill.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/cheesecakelabs.com\/blog\/ios-project-architecture-using-viper\/","og_locale":"en_US","og_type":"article","og_title":"iOS Project Architecture: VIPER Explained in Swift","og_description":"VIPER is an iOS project architecture built on View, Interactor, Presenter, Entity and Router. See how each part works in Swift, and when it's overkill.","og_url":"https:\/\/cheesecakelabs.com\/blog\/ios-project-architecture-using-viper\/","og_site_name":"Cheesecake Labs","article_publisher":"https:\/\/www.facebook.com\/cheesecakelabs","article_published_time":"2016-04-28T19:11:58+00:00","article_modified_time":"2026-08-15T08:45:44+00:00","og_image":[{"width":2076,"height":720,"url":"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2016\/04\/viper_architecture.jpg","type":"image\/jpeg"}],"author":"Cheesecake Labs","twitter_card":"summary_large_image","twitter_creator":"@cheesecakelabs","twitter_site":"@cheesecakelabs","twitter_misc":{"Written by":null,"Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/cheesecakelabs.com\/blog\/ios-project-architecture-using-viper\/#article","isPartOf":{"@id":"https:\/\/cheesecakelabs.com\/blog\/ios-project-architecture-using-viper\/"},"author":{"name":"Pedro Henrique Peralta"},"headline":"iOS Project Architecture: Using VIPER","datePublished":"2016-04-28T19:11:58+00:00","dateModified":"2026-08-15T08:45:44+00:00","mainEntityOfPage":{"@id":"https:\/\/cheesecakelabs.com\/blog\/ios-project-architecture-using-viper\/"},"wordCount":1288,"commentCount":4,"publisher":{"@id":"https:\/\/cheesecakelabs.com\/blog\/#organization"},"image":{"@id":"https:\/\/cheesecakelabs.com\/blog\/ios-project-architecture-using-viper\/#primaryimage"},"thumbnailUrl":"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2016\/04\/viper_architecture.jpg","keywords":["code","iOS development"],"articleSection":["Product Engineering","Engineering"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/cheesecakelabs.com\/blog\/ios-project-architecture-using-viper\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/cheesecakelabs.com\/blog\/ios-project-architecture-using-viper\/","url":"https:\/\/cheesecakelabs.com\/blog\/ios-project-architecture-using-viper\/","name":"iOS Project Architecture: VIPER Explained in Swift","isPartOf":{"@id":"https:\/\/cheesecakelabs.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cheesecakelabs.com\/blog\/ios-project-architecture-using-viper\/#primaryimage"},"image":{"@id":"https:\/\/cheesecakelabs.com\/blog\/ios-project-architecture-using-viper\/#primaryimage"},"thumbnailUrl":"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2016\/04\/viper_architecture.jpg","datePublished":"2016-04-28T19:11:58+00:00","dateModified":"2026-08-15T08:45:44+00:00","description":"VIPER is an iOS project architecture built on View, Interactor, Presenter, Entity and Router. See how each part works in Swift, and when it's overkill.","breadcrumb":{"@id":"https:\/\/cheesecakelabs.com\/blog\/ios-project-architecture-using-viper\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cheesecakelabs.com\/blog\/ios-project-architecture-using-viper\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cheesecakelabs.com\/blog\/ios-project-architecture-using-viper\/#primaryimage","url":"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2016\/04\/viper_architecture.jpg","contentUrl":"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2016\/04\/viper_architecture.jpg","width":2076,"height":720,"caption":"viper_architecture | | Cheesecake Labs"},{"@type":"BreadcrumbList","@id":"https:\/\/cheesecakelabs.com\/blog\/ios-project-architecture-using-viper\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cheesecakelabs.com\/blog\/"},{"@type":"ListItem","position":2,"name":"iOS Project Architecture: Using VIPER"}]},{"@type":"WebSite","@id":"https:\/\/cheesecakelabs.com\/blog\/#website","url":"https:\/\/cheesecakelabs.com\/blog\/","name":"Cheesecake Labs","description":"AI Implementation, Data and Product Engineering","publisher":{"@id":"https:\/\/cheesecakelabs.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/cheesecakelabs.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/cheesecakelabs.com\/blog\/#organization","name":"Cheesecake Labs","alternateName":"Cheesecake Labs Inc","url":"https:\/\/cheesecakelabs.com\/","logo":{"@type":"ImageObject","@id":"https:\/\/cheesecakelabs.com\/#logo","url":"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2022\/06\/cheesecake-labs-1.png","contentUrl":"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2022\/06\/cheesecake-labs-1.png","caption":"Cheesecake Labs","inLanguage":"en"},"image":{"@type":"ImageObject","@id":"https:\/\/cheesecakelabs.com\/#primary-image","url":"https:\/\/ckl-website-v4-strapi-prod.s3.us-east-2.amazonaws.com\/ai_software_development_company_83fb512983.webp","contentUrl":"https:\/\/ckl-website-v4-strapi-prod.s3.us-east-2.amazonaws.com\/ai_software_development_company_83fb512983.webp","width":1920,"height":1080,"caption":"Cheesecake Labs \u2014 AI, Data & Blockchain software development services","inLanguage":"en"},"sameAs":["https:\/\/www.facebook.com\/cheesecakelabs","https:\/\/x.com\/cheesecakelabs","https:\/\/www.instagram.com\/cheesecakelabs\/","https:\/\/www.linkedin.com\/company\/cheesecake-labs\/","https:\/\/www.youtube.com\/channel\/UCdGEQ5AHJcmIlaOaI5fGGVA","https:\/\/clutch.co\/profile\/cheesecake-labs","https:\/\/www.behance.net\/cheesecakelabs","https:\/\/dribbble.com\/cheesecakelabs","https:\/\/www.designrush.com\/agency\/profile\/cheesecake-labs","https:\/\/www.g2.com\/products\/cheesecake-labs\/reviews"],"description":"Cheesecake Labs is a software development studio that designs and builds custom digital products \u2014 web, mobile, and platforms \u2014 combining product design and high-performance engineering.","foundingDate":"2013"},{"@type":"Person","name":"Pedro Henrique Peralta","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cheesecakelabs.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2017\/09\/pedro-300x300.jpg","contentUrl":"https:\/\/ckl-website-static.s3.amazonaws.com\/wp-content\/uploads\/2017\/09\/pedro-300x300.jpg","caption":"Pedro Henrique Peralta"},"description":"10 years of experience in Marketing and Sales in the Technology sector. My main purpose is help, support and structure efficient operations and also develop independent and multidisciplinary teams.","url":"https:\/\/cheesecakelabs.com\/blog\/autor\/pedro-2\/"}]}},"_links":{"self":[{"href":"https:\/\/cheesecakelabs.com\/blog\/wp-json\/wp\/v2\/posts\/2644","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cheesecakelabs.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cheesecakelabs.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cheesecakelabs.com\/blog\/wp-json\/wp\/v2\/users\/65"}],"replies":[{"embeddable":true,"href":"https:\/\/cheesecakelabs.com\/blog\/wp-json\/wp\/v2\/comments?post=2644"}],"version-history":[{"count":3,"href":"https:\/\/cheesecakelabs.com\/blog\/wp-json\/wp\/v2\/posts\/2644\/revisions"}],"predecessor-version":[{"id":14763,"href":"https:\/\/cheesecakelabs.com\/blog\/wp-json\/wp\/v2\/posts\/2644\/revisions\/14763"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cheesecakelabs.com\/blog\/wp-json\/wp\/v2\/media\/2938"}],"wp:attachment":[{"href":"https:\/\/cheesecakelabs.com\/blog\/wp-json\/wp\/v2\/media?parent=2644"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cheesecakelabs.com\/blog\/wp-json\/wp\/v2\/categories?post=2644"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cheesecakelabs.com\/blog\/wp-json\/wp\/v2\/tags?post=2644"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}