{"id":13475113,"url":"https://github.com/bartleby/Core-iOS-Application-Architecture","last_synced_at":"2025-03-26T23:30:31.582Z","repository":{"id":72990189,"uuid":"171276991","full_name":"bartleby/Core-iOS-Application-Architecture","owner":"bartleby","description":"Core iOS Application Architecture - The development paradigm of clean, testable code and modular iOS applications. + Xcode templates","archived":false,"fork":false,"pushed_at":"2019-12-18T18:45:23.000Z","size":462,"stargazers_count":148,"open_issues_count":0,"forks_count":21,"subscribers_count":10,"default_branch":"master","last_synced_at":"2024-10-30T08:51:23.596Z","etag":null,"topics":["architecture","coordinator","ios","modular","mvc","mvp","template","viper","xcode-templates"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bartleby.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2019-02-18T12:04:53.000Z","updated_at":"2024-08-27T15:02:07.000Z","dependencies_parsed_at":null,"dependency_job_id":"a34758f8-6c49-457c-bf4b-713dd8561a21","html_url":"https://github.com/bartleby/Core-iOS-Application-Architecture","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bartleby%2FCore-iOS-Application-Architecture","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bartleby%2FCore-iOS-Application-Architecture/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bartleby%2FCore-iOS-Application-Architecture/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bartleby%2FCore-iOS-Application-Architecture/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bartleby","download_url":"https://codeload.github.com/bartleby/Core-iOS-Application-Architecture/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245753759,"owners_count":20666801,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["architecture","coordinator","ios","modular","mvc","mvp","template","viper","xcode-templates"],"created_at":"2024-07-31T16:01:17.473Z","updated_at":"2025-03-26T23:30:31.123Z","avatar_url":"https://github.com/bartleby.png","language":"Swift","funding_links":[],"categories":["Swift"],"sub_categories":[],"readme":"![Core-iOS-Application-Architecture](/images/header.png)\n\n## Overview\n\nMVP and MVC modules template has been deprecated!\n\nCore iOS Application Architecture - The development paradigm of clean, testable code and modular iOS applications.\n\nThis repository contains Xcode templates for quickly creating a project, modules, services and coordinator.\n\n\n![Core-Architecture](/images/core.png)\n\n## Contents\n\n* [Requirements](#requirements)\n  + [Example project](#example-project)\n* [Usage](#usage)\n  + [Project structure](#project-structure)\n  + [Project Template](#project-template)\n  + [Module Template](#module-template)\n  + [Service Template](#service-template-soa)\n  + [Coordinator Template](#coordinator-template)\n* [Code Style](#code-style)\n  + [Naming](#naming)\n* [Installation](#installation)\n* [Author](#author)\n* [License](#license)\n\n\n## Requirements\n\n* Xcode 10+\n* Swift 4.2+\n\n### Example project\n\n[Download](https://github.com/bartleby/CAA-Exemple-Project) example project built on the basis of this paradigm.\n\n\n## Usage\n\n#### Create new Project\n\n* Open Xcode\n* File \u003e New \u003e Project or press shortcuts ⇧⌘N\n* Choice MVC, MVP or VIPER Architecture\n* After you have created a project, you need to remove reference on the folder \"Classes\"\n  - Highlight the Classes folder in the Xcode Project Navigator\n  - Press Backspace Key\n  - Press \"Remove Reference\" in alert window\n* Now you need to return the \"Classes\" folder to the project.\n  - Drag the \"Classes\" folder from the Finder to the Xcode project\n* Profit! 🎉\n\n#### Create new Module, Service or Coordinator\n\n* Open Xcode Project\n* Select Modules, Services or Coordinators Group in Xcode Project Navigator\n* Create new file\n  - File \u003e New \u003e File... or press shortcuts ⌘N\n  - Choice Module (MVC, MVP or VIPER) Service or Coordinator\n  - Enter Name (if you wont to create \"Service\" you must specify at the end of the name \"Service\" for example - NetworkService or SettingsService)\n* After you have created a Service, Module or Coordinator, you need to remove reference on the folder\n  - Highlight the Folder in the Xcode Project Navigator\n  - Press Backspace Key\n  - Press \"Remove Reference\" in alert window\n* Now you need to return your Folder to the project.\n  - Drag the Folder from the Finder to the Xcode project\n* Profit! 🎉\n\nImportant! you need to add your Service, Module or Coordinator to the DI Container in AppDelegate.swift\n\n```Swift\n// Setup Coordinators\ncontainer.apply(AppCoordinatorAssembly.self)\ncontainer.apply(MainCoordinatorAssembly.self)\n// add your coordinator here\n\n// Setup Modules\ncontainer.apply(MainAssembly.self)\n// add your module here\n\n// Setup Services\ncontainer.apply(AppConfigServiceAssembly.self)\ncontainer.apply(EnvironmentServiceAssembly.self)\n// add your service here\n```\n\n### Project Template\n\n\u003cimg src=\"/images/project-viper.png\" align=\"left\" height=\"80px\"\u003e\n\u003cimg src=\"/images/project-mvp.png\" align=\"left\" height=\"80px\"\u003e\n\u003cimg src=\"/images/project-mvc.png\" align=\"left\" height=\"80px\"\u003e\n\n\u003cbr\u003e\n\u003cbr\u003e\n\u003cbr\u003e\n\u003cbr\u003e\n\nThere are 3 project templates, MVC, MVP and VIPER, the templates differ only in the main module architecture.\nThis does not affect the continued use of modules, you can create any modules based on the complexity of your screen.\nFor example, you plan a small project, then your choice is a project based on the MVP pattern.\n\n#### Each project template includes:\n- DeepLink out of the box\n- Launch Instructor\n- Plugable AppDelegate\n- [Swilby](https://github.com/bartleby/Swilby) Library for DI\n- Toolkit, Tweaks\n- Extensions\n- Router\n- etc.\n\n### Project structure\n\n* AppDelegate\n  - Services\n* Assemblys\n  - Coordinators\n  - Modules\n  - Services\n* Constants\n* Library\n  - Swilby\n* Utils\n  - Tweaks\n* Extensions\n  - Collection\n  - Numbers\n  - Codable\n  - Color\n  - Date\n  - URL\n  - FileManager\n  - View\n  - String\n  - NSObject\n* Common\n  - AppDelegateManager\n  - Coordinator\n  - Module\n  - ActionCloud\n  - View\n  - Protocols\n  - DeepLink\n  - Router\n\n\n\n### Module Template\n\n\u003cimg src=\"/images/module-viper.png\" align=\"left\" height=\"80px\" hspace=\"0px\" vspace=\"10px\"\u003e\n\u003cimg src=\"/images/module-mvp.png\" align=\"left\" height=\"80px\" hspace=\"0px\" vspace=\"10px\"\u003e\n\u003cimg src=\"/images/module-mvc.png\" align=\"left\" height=\"80px\" hspace=\"0px\" vspace=\"10px\"\u003e\n\n\u003cbr\u003e\n\u003cbr\u003e\n\u003cbr\u003e\n\u003cbr\u003e\n\nYou can use different modules in one project based on the complexity of your screen.\nOne screen - one module.\nFor example, you need to create a simple screen on which there will be a WebView with some information - your choice of MVC module,\nIf the screen assumes complex business logic, interaction with the server, etc., your choice is the VIPER module.\n\nAll your modules should be in the \"Modules\" folder along the path \"Classes/Assemblys/Modules\"\n\n#### VIPER Module structure\n\n* Module\n  - Storyboards\n  - Assembly\n  - Presenter\n  - Interactor\n  - View\n  - Protocols\n\n#### MVP Module structure\n\n* Module\n  - Storyboards\n  - Assembly\n  - Presenter\n  - View\n  - Protocols\n\n#### MVC Module structure\n\n* Module\n  - Storyboards\n  - Assembly\n  - View\n  - Protocols\n\n### Service Template (SoA)\n\n\u003cimg src=\"/images/service.png\" align=\"left\" height=\"80px\" hspace=\"0px\" vspace=\"10px\"\u003e\n\n\u003cbr\u003e\n\u003cbr\u003e\n\u003cbr\u003e\n\u003cbr\u003e\n\nEach service is engaged in its own business: the authorization service works with authorization, the user service with user data and so on. A good rule (a specific service works with one type of entity) is separation from the server side into different path: /auth, /user, /settings, but this is not necessary.\n\nAll your services should be in the \"Services\" folder along the path \"Classes/Assemblys/Services\"\n\nYou can learn more about the principle of developing SoA from [wikipedia](https://en.wikipedia.org/wiki/Service-oriented_architecture)\n\n\n### Coordinator Template\n\n\u003cimg src=\"/images/coordinator.png\" align=\"left\" height=\"80px\" hspace=\"0px\" vspace=\"10px\"\u003e\n\n\u003cbr\u003e\n\u003cbr\u003e\n\u003cbr\u003e\n\u003cbr\u003e\n\nCoordinator is an object that handles navigation flow and shares flow’s handling for the next coordinator after switching on the next chain. It means that coordinators should only keep navigation logic between screens. Coordinators can keep references to a storage, which holds data that is used by factories for creating modules, but they can never handle a module’s business logic and never drive a cell’s behavior.\n\nAll your coordinators should be in the \"Coordinators\" folder along the path \"Classes/Assemblys/Coordinators\"\n\nYou can learn more about the coordinators from the [article](https://medium.com/blacklane-engineering/coordinators-essential-tutorial-part-i-376c836e9ba7) by Andrey Panov.\n\n\n## Code Style\n\n### Naming\n\nGood clean code also depends on the correct naming.\n\n###### Wrong!\n```Swift\n@IBOutlet weak var descriptionText: UITextView!\n@IBOutlet weak var image: UIImageView!\n@IBOutlet weak var avatarIcon: UIImageView!\n@IBOutlet weak var labelTitle: UILabel!\n@IBOutlet weak var contentView: UIScrollView!\n\n```\n\n###### Right!\n```Swift\n\n@IBOutlet weak var descriptionTextView: UITextView!\n@IBOutlet weak var avatarImageView: UIImageView!\n@IBOutlet weak var titleLabel: UILabel!\n@IBOutlet weak var contentScrollView: UIScrollView!\n\n```\n\n###### Wrong!\n```Swift\n\nlet vc = NewsViewController()\nlet msg = Message()\nlet shape1 = Shape()\n\n```\n\n###### Right!\n```Swift\n\nlet newsViewController = NewsViewController()\nlet message = Message()\nlet square = Shape()\n\n```\n\n###### Wrong!\n```Swift\n\nview.hidden\nelement.expanded\narray.empty\n\n```\n\n###### Right!\n```Swift\n\nview.isHidden\nelement.isExpanded\narray.isEmpty\n\n```\n\n#### View Output\n\n###### Wrong!\n```Swift\nfunc viewLoaded()\nfunc authButtonTap()\nfunc textChanged(text: String)\n\n```\n\n###### Right!\n```Swift\n\nfunc viewDidLoad()\nfunc authButtonDidTap()\nfunc usernameTextFieldDidChange(value: String)\n\n```\n\n#### Module Output\n\n###### Wrong!\n```Swift\n\nvar authCancel: (() -\u003e Void)? { get set }\nvar authComplete: ((String) -\u003e Void)? { get set }\nvar userData: ((UserData) -\u003e Void)? { get set }\n\n```\n\n###### Right!\n```Swift\n\nvar onAuthCanceled: (() -\u003e Void)? { get set }\nvar onAuthCompleted: ((String) -\u003e Void)? { get set }\nvar onUserDataCompleted: ((UserData) -\u003e Void)? { get set }\n\n```\n\n#### Module Input\n\n###### Wrong!\n```Swift\n\nfunc token(_ token: String)\nfunc pageIndex(_ i: Int)\n\n```\n\n###### Right!\n```Swift\n\nfunc set(token: String)\nfunc setPage(index: Int)\n\n```\n\n#### Interactor Input\n\n###### Wrong!\n```Swift\n\nfunc getUser(_ completion: (User) -\u003e Void)\nfunc obtainUser(_ completion: (User) -\u003e ())\nfunc config() -\u003e Config\n\n```\n\n###### Right!\n\n```Swift\n\nfunc obtainUser(_ completion: (User) -\u003e Void)\nfunc obtainConfig(_ completion: (Config) -\u003e Void)\n\n```\n\n\n## Installation\n\nOnly need execute this command in terminal:\n\n```swift\nswift install.swift\n```\n\n## Author\n\n🦆 Alex Artemev [www.iDevs.io](https://iDevs.io)\n\n\n## License\n\nMIT License\n\nCopyright (c) 2019 Alex Artemev (iDevs.io)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbartleby%2FCore-iOS-Application-Architecture","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbartleby%2FCore-iOS-Application-Architecture","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbartleby%2FCore-iOS-Application-Architecture/lists"}