{"id":22358798,"url":"https://github.com/darrarski/swift-composable-app-example","last_synced_at":"2025-07-30T12:32:09.963Z","repository":{"id":52950766,"uuid":"334730608","full_name":"darrarski/swift-composable-app-example","owner":"darrarski","description":"Example iOS app built with module composition in mind.","archived":false,"fork":false,"pushed_at":"2021-04-12T17:11:30.000Z","size":847,"stargazers_count":85,"open_issues_count":2,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-05-02T05:10:39.773Z","etag":null,"topics":["composable-architecture","composition","swift","swift-package-manager","swiftui","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/darrarski.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}},"created_at":"2021-01-31T18:46:29.000Z","updated_at":"2024-02-08T22:02:24.000Z","dependencies_parsed_at":"2022-09-01T05:40:51.526Z","dependency_job_id":null,"html_url":"https://github.com/darrarski/swift-composable-app-example","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/darrarski%2Fswift-composable-app-example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darrarski%2Fswift-composable-app-example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darrarski%2Fswift-composable-app-example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darrarski%2Fswift-composable-app-example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/darrarski","download_url":"https://codeload.github.com/darrarski/swift-composable-app-example/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228133616,"owners_count":17874511,"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":["composable-architecture","composition","swift","swift-package-manager","swiftui","xcode"],"created_at":"2024-12-04T15:17:52.388Z","updated_at":"2024-12-04T15:17:53.500Z","avatar_url":"https://github.com/darrarski.png","language":"Swift","funding_links":["https://www.buymeacoffee.com/darrarski"],"categories":[],"sub_categories":[],"readme":"# Swift Composable App Example\n\n![swift: v5.3](https://img.shields.io/badge/swift-v5.3-orange.svg)\n![platform: iOS](https://img.shields.io/badge/platform-iOS-blue.svg)\n![deployment target: iOS 14](https://img.shields.io/badge/deployment%20target-iOS%2014-blueviolet)\n\n|1️⃣ Adjust color|2️⃣ Select shape|3️⃣ Preview result|\n|:--|:--|:--|\n|![Color screen](Misc/color_screen.png)|![Shape screen](Misc/shape_screen.png)|![Preview screen](Misc/preview_screen.png)|\n\n## 📝 Description\n\nThis repository contains an example iOS app built with module composition in mind. It shows how to organize source code into separate modules, where each of them is responsible for providing different functionality in the app.\n\nInstead of splitting the code into separate Xcode's targets that produce frameworks, this project uses Swift Package Manager support in Xcode. There is a single iOS application target in the Xcode project (with corresponding unit tests target) and several Swift packages for each corresponding app feature. Some of the advantages of this setup are:\n\n👍 **Easier to maintain project structure**. Swift packages do not contain massive configuration in the form of `.pbxproj` file. The disk's file structure is what you work on in Xcode, and it stays in sync with it. Files are sorted alphabetically. Every folder on the disk automatically becomes a group in Xcode.\n\n👍 **Better cooperation in a team**. Because there are no entries in `.pbxproj` for every newly added or moved file, you can avoid hard to resolve conflicts in a version control system.\n\n👍 **Easier code reusability**. You can easily extract the package and use it in another project. Everything you need is to copy the package directory from one project to another.\n\n👍 **Easier to manage dependencies** (as long as you use Swift Package Manager). All the libraries your code depends on are defined in `Package.swift` file. Linking between your libraries is also easy and defined in the same file. The only thing you have to do in Xcode is embedding all your package libraries in the app target.\n\n👍 **Easier module separation**. It's straightforward to create a new module and extract a piece of your source code to it. You can focus on the app architecture and save the time you would spend creating and configuring Xcode targets.  As a result, you can achieve better composition and separation in your codebase.\n\n## 🛠 Tech Stack\n\n- [Xcode](https://developer.apple.com/xcode/) 12.4\n- [Swift](https://swift.org/) 5.3\n\n### 🧰 Frameworks \n\n- [SwiftUI](https://developer.apple.com/documentation/swiftui)\n- [ComposableArchitecture](http://github.com/pointfreeco/swift-composable-architecture/)\n- [SnapshotTesting](https://github.com/pointfreeco/swift-snapshot-testing)\n\n## 🚀 Quick start\n\nOpen `ComposableApp.xcodeproj` in Xcode. You can run the app using the `ComposableApp` build scheme. Other schemes are for building and testing individual modules of the project.\n\n## 🏛 Architecture\n\nThe following diagram explains how the project is structured:\n\n```\n+---------------+               +--------------+       +---------------+\n|      App      +\u003c--------------+    Common    +\u003c--+---+   Library A   |\n+----+-----+----+               +---+---+---+--+   |   +---------------+\n     ^     ^                        |   |   |      |\n     |     |    +---------------+   |   |   |      |   +---------------+\n     |     +----+   Feature A   +\u003c--+   |   |      +---+   Library B   |\n     |          +---------------+       |   |      |   +---------------+\n     |                                  |   |      |\n     |          +---------------+       |   |      |   +---------------+\n     +----------+   Feature B   +\u003c------+   |      +---+   Library C   |\n                +---------------+           |          +---------------+\n                       ^                    |    \n                       |                    |\n                +---------------+           |\n                +   Feature C   +\u003c----------+\n                +---------------+\n```\n\n- **App** - The application module\n- **Feature** - Feature-specific module\n- **Common** - A module containing shared logic and linking external dependencies\n- **Library** - External dependency\n- **A ← B** - Module A depends on module B\n\nFor easy module separation this project uses [ComposableArchitecture](http://github.com/pointfreeco/swift-composable-architecture/) library by [Point-Free](https://www.pointfree.co). \n\n### 🎯 Xcode project\n\n|Target|Kind|Description|\n|:--|:--|:--|\n|`App`|iOS app|Main target of the app.|\n|`AppTests`|iOS unit tests target|Unit tests of the app target.|\n\nAll Swift package libraries are embedded in the `App` target. The only exception is the `Testing` library used by unit test targets only and not embedded in the app.\n\n### 📦 Common package\n\n|Target|Kind|Description|\n|:--|:--|:--|\n|`Common`|library|Contains shared logic and links external dependencies.|\n|`CommonTests`|unit tests|Shared logic tests.|\n\nEvery other Swift package library in the project depends on the `Common` library. The purpose of this library is to contain source code that can be shared across the whole codebase and to link external libraries. It's a single place where external dependencies are defined.\n\n### 📦 Tabs package\n\n|Target|Kind|Description|\n|:--|:--|:--|\n|`Tabs`|library|Contains tabbed user interface with screens defined in other libraries.|\n|`TabsTests`|unit tests|Unit and snapshot tests of the tabbed user interface.|\n\n`Tabs` library depends on `Color`, `Shape` and `Preview` libraries, which contain screens presented in the tabbed user interface. It also binds the logic of these screens and handles communication between them.\n\n### 📦 Color package\n\n|Target|Kind|Description|\n|:--|:--|:--|\n|`Color`|library|Contains color picker screen.|\n|`ColorTests`|unit tests|Unit and snapshot tests of the color picker screen.|\n\nThis package is a feature module that contains a color picker screen in isolation from other modules.\n\n### 📦 Shape package\n\n|Target|Kind|Description|\n|:--|:--|:--|\n|`Shape`|library|Contains shape picker screen.|\n|`ShapeTests`|unit tests|Unit and snapshot tests of the shape picker screen.|\n\nThis package is a feature module that contains a shape picker screen in isolation from other modules.\n\n### 📦 Preview package\n\n|Target|Kind|Description|\n|:--|:--|:--|\n|`Preview`|library|Contains screen with a preview of a shape in a given color.|\n|`PreviewTests`|unit tests|Unit and snapshot tests of the preview screen.|\n\nThis package is a feature module that contains a shape preview screen. `Preview` library depends on `Color` and `Shape` libraries and uses models defined by them.\n\n### 📦 Testing package\n\n|Target|Kind|Description|\n|:--|:--|:--|\n|`Testing`|library|Contains shared testing logic and links external test dependencies.|\n\nEvery other Swift package unit tests target depends on the `Testing` library. This way, it's a single place where external test dependencies are defined.\n\n## 🧪 Tests\n\nThere is a unit testing target that tests the main app target. This one is managed by Xcode in a traditional way. All Swift packages in the project contain a test target in addition to a library product target. You can run tests for them from Xcode by selecting a given module build scheme.\n\nThe project contains **snapshot tests** of SwiftUI views. These were recorded using iPhone 12 simulator and should be run using it. Otherwise, you can experience snapshot test failures caused by screen resolution mismatch.\n\n## ☕️ Do you like the project?\n\n\u003ca href=\"https://www.buymeacoffee.com/darrarski\" target=\"_blank\"\u003e\u003cimg src=\"https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png\" alt=\"Buy Me A Coffee\" height=\"60\" width=\"217\" style=\"height: 60px !important;width: 217px !important;\" \u003e\u003c/a\u003e\n\n## 📄 License\n\nCopyright © 2021 [Dariusz Rybicki Darrarski](http://darrarski.pl)\n\nLicense: [MIT](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdarrarski%2Fswift-composable-app-example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdarrarski%2Fswift-composable-app-example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdarrarski%2Fswift-composable-app-example/lists"}