[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-6781":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":17,"stars30d":18,"stars90d":16,"forks30d":16,"starsTrendScore":19,"compositeScore":20,"rankGlobal":10,"rankLanguage":10,"license":21,"archived":22,"fork":22,"defaultBranch":23,"hasWiki":22,"hasPages":22,"topics":24,"createdAt":10,"pushedAt":10,"updatedAt":40,"readmeContent":41,"aiSummary":42,"trendingCount":16,"starSnapshotCount":16,"syncStatus":43,"lastSyncTime":44,"discoverSource":45},6781,"clean-architecture-swiftui","nalexn\u002Fclean-architecture-swiftui","nalexn","SwiftUI sample app using Clean Architecture. Examples of working with SwiftData persistence, networking, dependency injection, unit testing, and more.","",null,"Swift",6569,818,110,20,0,5,34,1,39.74,"MIT License",false,"master",[25,26,27,28,29,30,31,32,33,34,35,36,37,38,39],"architecture","clean-architecture","cleanarchitecture","demo","example-project","interactor","mvvm","sample","swift","swift-data","swift-testing","swiftdata","swiftui","swiftui-example","viewinspector","2026-06-12 02:01:30","### Articles related to this project\n\n* [Clean Architecture for SwiftUI](https:\u002F\u002Fnalexn.github.io\u002Fclean-architecture-swiftui\u002F?utm_source=nalexn_github)\n* [Programmatic navigation in SwiftUI project](https:\u002F\u002Fnalexn.github.io\u002Fswiftui-deep-linking\u002F?utm_source=nalexn_github)\n* [Separation of Concerns in Software Design](https:\u002F\u002Fnalexn.github.io\u002Fseparation-of-concerns\u002F?utm_source=nalexn_github)\n\n---\n\n# Clean Architecture for SwiftUI + Combine\n\nA demo project showcasing the setup of the SwiftUI app with Clean Architecture.\n\nThe app uses the [restcountries.com](https:\u002F\u002Frestcountries.com\u002F) REST API to show the list of countries and details about them.\n\n**Check out [mvvm branch](https:\u002F\u002Fgithub.com\u002Fnalexn\u002Fclean-architecture-swiftui\u002Ftree\u002Fmvvm) for the MVVM revision of the same app.**\n\nFor the example of handling the **authentication state** in the app, you can refer to my [other tiny project](https:\u002F\u002Fgithub.com\u002Fnalexn\u002Fuikit-swiftui) that harnesses the locks and keys principle for solving this problem.\n\n![platforms](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fplatforms-iPhone%20%7C%20iPad%20%7C%20macOS-lightgrey) [![codecov](https:\u002F\u002Fcodecov.io\u002Fgh\u002Fnalexn\u002Fclean-architecture-swiftui\u002Fbranch\u002Fmaster\u002Fgraph\u002Fbadge.svg)](https:\u002F\u002Fcodecov.io\u002Fgh\u002Fnalexn\u002Fclean-architecture-swiftui) [![codebeat badge](https:\u002F\u002Fcodebeat.co\u002Fbadges\u002Fdb33561b-0b2b-4ee1-a941-a08efbd0ebd7)](https:\u002F\u002Fcodebeat.co\u002Fprojects\u002Fgithub-com-nalexn-clean-architecture-swiftui-master)\n\n\u003Cp align=\"center\">\n  \u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Fnalexn\u002Fblob_files\u002Fblob\u002Fmaster\u002Fimages\u002Fcountries_preview.png?raw=true\" alt=\"Diagram\"\u002F>\n\u003C\u002Fp>\n\n## Key features\n* End of 2024 update: the project was fully revamped to use modern iOS stack technologies\n* Decoupled **Presentation**, **Business Logic**, and **Data Access** layers\n* Programmatic navigation. Push notifications with deep link\n* Redux-like centralized `AppState` as the single source of truth\n* Native SwiftUI dependency injection\n* Handling of the system events (such as `didBecomeActive`, `willResignActive`)\n* Full test coverage, including the UI (thanks to the [ViewInspector](https:\u002F\u002Fgithub.com\u002Fnalexn\u002FViewInspector))\n* Simple yet flexible networking layer built on async - await\n* UI - vanilla **SwiftUI** + **Combine**\n* Data persistence with **SwiftData**\n\n## Architecture overview\n\n\u003Cp align=\"center\">\n  \u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Fnalexn\u002Fblob_files\u002Fblob\u002Fmaster\u002Fimages\u002Fswiftui_arc_001.png?raw=true\" alt=\"Diagram\"\u002F>\n\u003C\u002Fp>\n\n### Presentation Layer\n\n**SwiftUI views** that contain no business logic and are a function of the state.\n\nSide effects are triggered by the user's actions (such as a tap on a button) or view lifecycle event `onAppear` and are forwarded to the `Interactors`.\n\nState and business logic layer (`AppState` + `Interactors`) are natively injected into the view hierarchy with `@Environment`.\n\n### Business Logic Layer\n\nBusiness Logic Layer is represented by `Interactors`. \n\nInteractors receive requests to perform work, such as obtaining data from an external source or making computations, but they never return data back directly.\n\nInstead, they forward the result to the `AppState` or to a `Binding`. The latter is used when the result of work (the data) is used locally by one View and does not belong to the `AppState`.\n\n[Previously](https:\u002F\u002Fgithub.com\u002Fnalexn\u002Fclean-architecture-swiftui\u002Freleases\u002Ftag\u002F1.0), this app did not use CoreData for persistence, and all loaded data were stored in the `AppState`.\n\nWith the persistence layer in place we have a choice - either to load the DB content onto the `AppState`, or serve the data from `Interactors` on an on-demand basis through `Binding`.\n\nThe first option suits best when you don't have a lot of data, for example, when you just store the last used login email in the `UserDefaults`. Then, the corresponding string value can just be loaded onto the `AppState` at launch and updated by the `Interactor` when the user changes the input.\n\nThe second option is better when you have massive amounts of data and introduce a fully-fledged database for storing it locally.\n\n### Data Access Layer\n\nData Access Layer is represented by `Repositories`.\n\nRepositories provide asynchronous API (`Publisher` from Combine) for making [CRUD](https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FCreate,_read,_update_and_delete) operations on the backend or a local database. They don't contain business logic, neither do they mutate the `AppState`. Repositories are accessible and used only by the Interactors.\n\n---\n\n[![Twitter](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Ftwitter-nallexn-blue)](https:\u002F\u002Ftwitter.com\u002Fnallexn) [![blog](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fblog-github-blue)](https:\u002F\u002Fnalexn.github.io\u002F?utm_source=nalexn_github)\n","该项目是一个采用Clean Architecture架构的SwiftUI示例应用，展示了如何使用SwiftData持久化、网络请求、依赖注入以及单元测试等技术。核心功能包括解耦的展示层、业务逻辑层和数据访问层，支持程序化导航与深度链接，并通过Redux风格的集中式状态管理确保单一数据源。此外，项目还实现了系统事件处理及全面的测试覆盖，包括UI测试。适合于希望学习或实践现代iOS开发中Clean Architecture模式的开发者，特别是那些对SwiftUI与Combine框架感兴趣的人士。",2,"2026-06-11 03:08:51","top_language"]