{"id":14697264,"url":"https://github.com/denissimon/iOS-MVVM-Clean-Architecture","last_synced_at":"2025-09-10T03:31:59.319Z","repository":{"id":87339872,"uuid":"242413689","full_name":"denissimon/iOS-Clean-Explicit-Architecture","owner":"denissimon","description":"Example iOS app designed using Clean \u0026 Explicit Architecture hybrid.","archived":false,"fork":false,"pushed_at":"2024-07-16T21:41:11.000Z","size":6967,"stargazers_count":13,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-07-16T22:46:44.040Z","etag":null,"topics":["app","architecture","async-await","clean-architecture","clean-code","coordinator","explicit-architecture","ios","ios-app","mvvm","mvvm-architecture","mvvm-c","swift","swift-concurrency","viewmodel","xcode"],"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/denissimon.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,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-02-22T21:23:56.000Z","updated_at":"2024-07-16T22:46:59.047Z","dependencies_parsed_at":null,"dependency_job_id":"496a2bf0-b249-44fd-b0f3-d958922bebde","html_url":"https://github.com/denissimon/iOS-Clean-Explicit-Architecture","commit_stats":null,"previous_names":["denissimon/ios-mvvm-clean-architecture","denissimon/ios-clean-explicit-architecture"],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/denissimon%2FiOS-Clean-Explicit-Architecture","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/denissimon%2FiOS-Clean-Explicit-Architecture/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/denissimon%2FiOS-Clean-Explicit-Architecture/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/denissimon%2FiOS-Clean-Explicit-Architecture/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/denissimon","download_url":"https://codeload.github.com/denissimon/iOS-Clean-Explicit-Architecture/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":232492467,"owners_count":18531965,"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":["app","architecture","async-await","clean-architecture","clean-code","coordinator","explicit-architecture","ios","ios-app","mvvm","mvvm-architecture","mvvm-c","swift","swift-concurrency","viewmodel","xcode"],"created_at":"2024-09-13T07:01:04.900Z","updated_at":"2025-09-10T03:31:59.302Z","avatar_url":"https://github.com/denissimon.png","language":"Swift","funding_links":[],"categories":["Sample"],"sub_categories":["RSS"],"readme":"# iOS-MVVM-Clean-Architecture\n[![Swift Version](https://img.shields.io/badge/Swift-5.5+-F16D39.svg?style=flat)](https://swift.org)\n[![Platforms](https://img.shields.io/badge/platform-iOS-lightgrey.svg)](https://developer.apple.com/swift/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/denissimon/iOS-MVVM-Clean-Architecture/blob/master/LICENSE)\n\nExample iOS app designed using MVVM-C and Clean Architecture. Uses Swift Concurrency.\n\nThe app retrieves images for any search query or tag via the Flickr API. It has three modules: ImageSearch, ImageDetails, HotTags.\n\n\u003ctable\u003e \n  \u003ctr\u003e\n    \u003ctd\u003e\u003cimg src=\"Screenshots/1_iOS-MVVM-Clean-Architecture.png\" width=\"252\"\u003e\u003c/td\u003e\n    \u003ctd\u003e\u003cimg src=\"Screenshots/2_iOS-MVVM-Clean-Architecture.png\" width=\"252\"\u003e\u003c/td\u003e\n    \u003ctd\u003e\u003cimg src=\"Screenshots/3_iOS-MVVM-Clean-Architecture.png\" width=\"252\"\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n### Architecture concepts used here\n\n- [Clean Architecture][CleanArchitectureLink]\n- [Explicit Architecture][ExplicitArchitectureLink]\n- [MVVM][MVVMLink]\n- [Flow coordinator][FlowCoordinatorLink] implemented with closure-based actions\n- [Dependency Injection][DIContainerLink], DIContainer\n- [Protocol-Oriented Programming][POPLink]\n- [Data Binding][DataBindingLink] using the lightweight [Observable\\\u003cT\\\u003e][ObservableLink]\n- [Closure-based delegation][ClosureBasedDelegationLink] using the lightweight [Event\\\u003cT\\\u003e][EventLink]\n- [Pure functional transformations][PureFunctionalTransformationsLink]\n- [Delegating entity behavior][DelegatingEntityBehaviorLink]\n- [Alternative DTO approach][AlternativeDTOApproachLink]\n\n[CleanArchitectureLink]: https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html\n[ExplicitArchitectureLink]: https://herbertograca.com/2017/11/16/explicit-architecture-01-ddd-hexagonal-onion-clean-cqrs-how-i-put-it-all-together\n[MVVMLink]: https://github.com/denissimon/iOS-MVVM-Clean-Architecture/tree/master/ImageSearch/Presentation/ImagesFeature/ImageSearch\n[FlowCoordinatorLink]: https://github.com/denissimon/iOS-MVVM-Clean-Architecture/tree/master/ImageSearch/Coordinator\n[DIContainerLink]: https://github.com/denissimon/iOS-MVVM-Clean-Architecture/blob/master/ImageSearch/Coordinator/DIContainer/DIContainer.swift\n[POPLink]: https://www.swiftanytime.com/blog/protocol-oriented-programming-in-swift\n[DataBindingLink]: https://github.com/denissimon/iOS-MVVM-Clean-Architecture/blob/master/ImageSearch/Presentation/ImagesFeature/ImageSearch/ViewModel/DefaultImageSearchViewModel.swift\n[ObservableLink]: https://github.com/denissimon/iOS-MVVM-Clean-Architecture/blob/master/ImageSearch/Common/Utils/SwiftEvents.swift#L86\n[ClosureBasedDelegationLink]: https://github.com/denissimon/iOS-MVVM-Clean-Architecture/blob/master/ImageSearch/Presentation/ImagesFeature/HotTags/ViewModel/DefaultHotTagsViewModel.swift\n[EventLink]: https://github.com/denissimon/iOS-MVVM-Clean-Architecture/blob/master/ImageSearch/Common/Utils/SwiftEvents.swift\n[PureFunctionalTransformationsLink]: https://blog.ploeh.dk/2020/03/02/impureim-sandwich\n[DelegatingEntityBehaviorLink]: https://github.com/denissimon/iOS-MVVM-Clean-Architecture/blob/master/ImageSearch/Domain/Entities/Behaviors/ImageBehavior.swift\n[AlternativeDTOApproachLink]: https://medium.com/geekculture/why-we-shouldnt-use-data-transfer-objects-in-swift-38dcef529a66\n\n### Includes\n\n- Reusable and universal [NetworkService][NetworkServiceLink] based on URLSession\n- Reusable and universal [SQLite][SQLiteAdapterLink] wrapper around SQLite3\n- [Image caching service][ImageCachingServiceLink]\n- Configurable use of [UIKit][UIKitViewLink] or [SwiftUI][SwiftUIViewLink] for the same screen\n- Advanced error handling\n- Unit and integration tests for a number of components from all layers\n\n[NetworkServiceLink]: https://github.com/denissimon/iOS-MVVM-Clean-Architecture/blob/master/ImageSearch/Data/Network/NetworkService/NetworkService.swift\n[SQLiteAdapterLink]: https://github.com/denissimon/iOS-MVVM-Clean-Architecture/tree/master/ImageSearch/Data/Persistence/SQLite\n[ImageCachingServiceLink]: https://github.com/denissimon/iOS-MVVM-Clean-Architecture/blob/master/ImageSearch/Domain/Services/ImageCachingService.swift\n[UIKitViewLink]: https://github.com/denissimon/iOS-MVVM-Clean-Architecture/blob/master/ImageSearch/Presentation/ImagesFeature/HotTags/View/UIKit/HotTagsViewController.swift\n[SwiftUIViewLink]: https://github.com/denissimon/iOS-MVVM-Clean-Architecture/blob/master/ImageSearch/Presentation/ImagesFeature/HotTags/View/SwiftUI/HotTagsView.swift\n\n### Main layers\n\n**Presentation (MVVM)**: _coordinators_, _UI elements_, _SwiftUI views_, _UIKit storyboards_, _ViewControllers_, _ViewModels_\n\n**Domain**: _entities_, _use cases_, _services_, _interfaces_\n\n**Data**: _entity repositories_, _APIs_, _API/DB interactors_ (or network services and persistent storages), _adapters_\n\n[Detailed architecture overview][ArchitectureOverviewLink]\n\n[ArchitectureOverviewLink]: https://github.com/denissimon/iOS-MVVM-Clean-Architecture/blob/master/Docs/Architecture-overview.md\n\n### Use case scenarios\n\nImageSearch module:\n```swift\n* searchImagesUseCase.execute(imageQuery)\n* imageCachingService.cacheIfNecessary(data)\n* imageCachingService.getCachedImages(searchId: searchId)\n```\n\nImageDetails module:\n```swift\n* getBigImageUseCase.execute(for: image)\n```\n\nHotTags module:\n```swift\n* getHotTagsUseCase.execute()\n```\n\n### Image caching service\n\n[ImageCachingService][ImageCachingServiceLink] implements the logic for caching downloaded images and freeing memory. This helps keep the app's memory usage under control, since there can be a lot of downloaded images, and without caching, the app could quickly accumulate hundreds of MB of memory used. Downloaded images are cached and read from the cache automatically.\n\n### Reusable components from this project\n\n- [SwiftEvents](https://github.com/denissimon/SwiftEvents) - the easiest way to implement data binding and notifications. Includes Event\\\u003cT\\\u003e and Observable\\\u003cT\\\u003e. Has a thread-safe version.\n- [URLSessionAdapter](https://github.com/denissimon/URLSessionAdapter) - a Codable wrapper around URLSession for networking\n- [SQLiteAdapter](https://github.com/denissimon/SQLiteAdapter) - a simple wrapper around SQLite3\n\n### Swift 6 support\n\nFor a Swift 6 version with SWIFT_STRICT_CONCURRENCY = complete, see the [swift6][Swift6Link] branch.\n\n[Swift6Link]: https://github.com/denissimon/iOS-MVVM-Clean-Architecture/tree/swift6\n\n### Requirements\n\niOS 15.0+, Xcode 13.0+, Swift 5.5+\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdenissimon%2FiOS-MVVM-Clean-Architecture","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdenissimon%2FiOS-MVVM-Clean-Architecture","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdenissimon%2FiOS-MVVM-Clean-Architecture/lists"}