{"id":13908345,"url":"https://github.com/pointfreeco/swift-dependencies","last_synced_at":"2025-05-13T22:12:17.476Z","repository":{"id":65187287,"uuid":"543149227","full_name":"pointfreeco/swift-dependencies","owner":"pointfreeco","description":"A dependency management library inspired by SwiftUI's \"environment.\"","archived":false,"fork":false,"pushed_at":"2025-05-01T14:02:57.000Z","size":1448,"stargazers_count":1827,"open_issues_count":7,"forks_count":149,"subscribers_count":22,"default_branch":"main","last_synced_at":"2025-05-07T15:53:18.602Z","etag":null,"topics":["architecture","dependency-injection","dependency-management","swift"],"latest_commit_sha":null,"homepage":"https://www.pointfree.co","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/pointfreeco.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","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,"zenodo":null}},"created_at":"2022-09-29T13:51:13.000Z","updated_at":"2025-05-06T21:27:52.000Z","dependencies_parsed_at":"2023-10-11T23:00:18.742Z","dependency_job_id":"51d9b2a5-c635-41d5-8b8f-c627115923cd","html_url":"https://github.com/pointfreeco/swift-dependencies","commit_stats":{"total_commits":193,"total_committers":37,"mean_commits":5.216216216216216,"dds":0.6994818652849741,"last_synced_commit":"a0f3ffd32a670d48a2e7fe96ffd67919acf3d448"},"previous_names":[],"tags_count":49,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pointfreeco%2Fswift-dependencies","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pointfreeco%2Fswift-dependencies/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pointfreeco%2Fswift-dependencies/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pointfreeco%2Fswift-dependencies/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pointfreeco","download_url":"https://codeload.github.com/pointfreeco/swift-dependencies/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254036843,"owners_count":22003654,"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","dependency-injection","dependency-management","swift"],"created_at":"2024-08-06T23:02:39.504Z","updated_at":"2025-05-13T22:12:17.468Z","avatar_url":"https://github.com/pointfreeco.png","language":"Swift","funding_links":[],"categories":["HarmonyOS","Swift"],"sub_categories":["Windows Manager"],"readme":"# Dependencies\n\nA dependency management library inspired by SwiftUI's \"environment.\"\n\n[![CI](https://github.com/pointfreeco/swift-dependencies/actions/workflows/ci.yml/badge.svg)](https://github.com/pointfreeco/swift-dependencies/actions/workflows/ci.yml)\n[![Slack](https://img.shields.io/badge/slack-chat-informational.svg?label=Slack\u0026logo=slack)](http://pointfree.co/slack-invite)\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fpointfreeco%2Fswift-dependencies%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/pointfreeco/swift-dependencies)\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fpointfreeco%2Fswift-dependencies%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/pointfreeco/swift-dependencies)\n\n  * [Learn More](#learn-more)\n  * [Overview](#overview)\n  * [Quick start](#quick-start)\n  * [Examples](#examples)\n  * [Documentation](#documentation)\n  * [Installation](#installation)\n  * [Community](#community)\n  * [Extensions](#extensions)\n  * [Alternatives](#alternatives)\n  * [License](#license)\n\n## Learn More\n\nThis library was motivated and designed over the course of many episodes on\n[Point-Free](https://www.pointfree.co), a video series exploring functional programming and the\nSwift language, hosted by [Brandon Williams](https://twitter.com/mbrandonw) and [Stephen\nCelis](https://twitter.com/stephencelis).\n\n\u003ca href=\"https://www.pointfree.co\"\u003e\n  \u003cimg alt=\"video poster image\" src=\"https://d3rccdn33rt8ze.cloudfront.net/episodes/0209.jpeg\" width=\"600\"\u003e\n\u003c/a\u003e\n\n## Overview\n\nDependencies are the types and functions in your application that need to interact with outside\nsystems that you do not control. Classic examples of this are API clients that make network\nrequests to servers, but also seemingly innocuous things such as `UUID` and `Date` initializers,\nfile access, user defaults, and even clocks and timers, can all be thought of as dependencies.\n\nYou can get really far in application development without ever thinking about dependency management \n(or, as some like to call it, \"dependency injection\"), but eventually uncontrolled dependencies can \ncause many problems in your code base and development cycle:\n\n  * Uncontrolled dependencies make it **difficult to write fast, deterministic tests** because you \n    are susceptible to the vagaries of the outside world, such as file systems, network \n    connectivity, internet speed, server uptime, and more.\n    \n  * Many dependencies **do not work well in SwiftUI previews**, such as location managers and speech\n    recognizers, and some **do not work even in simulators**, such as motion managers, and more. \n    This prevents you from being able to easily iterate on the design of features if you make use of \n    those frameworks.\n\n  * Dependencies that interact with 3rd party, non-Apple libraries (such as Firebase, web socket\n    libraries, network libraries, etc.) tend to be heavyweight and take a **long time to compile**. \n    This can slow down your development cycle.\n\nFor these reasons, and a lot more, it is highly encouraged for you to take control of your\ndependencies rather than letting them control you.\n\nBut, controlling a dependency is only the beginning. Once you have controlled your dependencies, \nyou are faced with a whole set of new problems:\n\n  * How can you **propagate dependencies** throughout your entire application in a way that is more\n    ergonomic than explicitly passing them around everywhere, but safer than having a global\n    dependency?\n    \n  * How can you **override dependencies** for just one portion of your application? This can be \n    handy for overriding dependencies for tests and SwiftUI previews, as well as specific user \n    flows such as onboarding experiences.\n    \n  * How can you be sure you **overrode _all_ dependencies** a feature uses in tests? It would be\n    incorrect for a test to mock out some dependencies but leave others as interacting with the\n    outside world.\n\nThis library addresses all of the points above, and much, _much_ more.\n\n## Quick start\n\nThe library allows you to register your own dependencies, but it also comes with many controllable\ndependencies out of the box (see [`DependencyValues`][dep-values-docs] for a full list), and there\nis a good chance you can immediately make use of one. If you are using `Date()`, `UUID()`,\n`Task.sleep`, or Combine schedulers directly in your feature's logic, you can already start to use\nthis library.\n\n```swift\n@Observable\nfinal class FeatureModel {\n  var items: [Item] = []\n\n  @ObservationIgnored\n  @Dependency(\\.continuousClock) var clock  // Controllable way to sleep a task\n  @ObservationIgnored\n  @Dependency(\\.date.now) var now           // Controllable way to ask for current date\n  @ObservationIgnored\n  @Dependency(\\.mainQueue) var mainQueue    // Controllable scheduling on main queue\n  @ObservationIgnored\n  @Dependency(\\.uuid) var uuid              // Controllable UUID creation\n\n  // ...\n}\n```\n\nOnce your dependencies are declared, rather than reaching out to the `Date()`, `UUID()`, etc.,\ndirectly, you can use the dependency that is defined on your feature's model:\n\n```swift\n@Observable\nfinal class FeatureModel {\n  // ...\n\n  func addButtonTapped() async throws {\n    try await clock.sleep(for: .seconds(1))  // 👈 Don't use 'Task.sleep'\n    items.append(\n      Item(\n        id: uuid(),  // 👈 Don't use 'UUID()'\n        name: \"\",\n        createdAt: now  // 👈 Don't use 'Date()'\n      )\n    )\n  }\n}\n```\n\nThat is all it takes to start using controllable dependencies in your features. With that little\nbit of upfront work done you can start to take advantage of the library's powers.\n\nFor example, you can easily control these dependencies in tests. If you want to test the logic\ninside the `addButtonTapped` method, you can use the [`withDependencies`][withdependencies-docs]\nfunction to override any dependencies for the scope of one single test. It's as easy as 1-2-3:\n\n```swift\n@Test\nfunc add() async throws {\n  let model = withDependencies {\n    // 1️⃣ Override any dependencies that your feature uses.\n    $0.clock = .immediate\n    $0.date.now = Date(timeIntervalSinceReferenceDate: 1234567890)\n    $0.uuid = .incrementing\n  } operation: {\n    // 2️⃣ Construct the feature's model\n    FeatureModel()\n  }\n  // 3️⃣ The model now executes in a controlled environment of dependencies,\n  //    and so we can make assertions against its behavior.\n  try await model.addButtonTapped()\n  #expect(\n    model.items == [\n      Item(\n        id: UUID(uuidString: \"00000000-0000-0000-0000-000000000000\")!,\n        name: \"\",\n        createdAt: Date(timeIntervalSinceReferenceDate: 1234567890)\n      )\n    ]\n  )\n}\n```\n\nHere we controlled the `date` dependency to always return the same date, and we controlled the\n`uuid` dependency to return an auto-incrementing UUID every time it is invoked, and we even \ncontrolled the `clock` dependency using an [`ImmediateClock`][immediate-clock-docs] to squash all\nof time into a single instant. If we did not control these dependencies this test would be very \ndifficult to write since there is no way to accurately predict what will be returned by `Date()` \nand `UUID()`, and we'd have to wait for real world time to pass, making the test slow.\n\nBut, controllable dependencies aren't only useful for tests. They can also be used in Xcode\npreviews. Suppose the feature above makes use of a clock to sleep for an amount of time before\nsomething happens in the view. If you don't want to literally wait for time to pass in order to see\nhow the view changes, you can override the clock dependency to be an \"immediate\" clock using\n`prepareDependencies`:\n\n```swift\n#Preview {\n  let _ = prepareDependencies {\n    $0.continuousClock = ImmediateClock()\n  }\n  // All access of '@Dependency(\\.continuousClock)' in this preview will \n  // use an immediate clock.\n  FeatureView(model: FeatureModel())\n}\n```\n\nThis will make it so that the preview uses an immediate clock when run, but when running in a\nsimulator or on device it will still use a live `ContinuousClock`. This makes it possible to\noverride dependencies just for previews without affecting how your app will run in production.\n\nThat is the basics to getting started with using the library, but there is still a lot more you\ncan do. You can learn more in depth about the library by exploring the [documentation][docs]\nand articles:\n\n#### Getting started\n\n* **[Quick start][quick-start-article] (Same as the information above)**:\n  Learn the basics of getting started with the library before diving deep into all of its features.\n\n* **[What are dependencies?][what-are-dependencies-article]**:\n  Learn what dependencies are, how they complicate your code, and why you want to control them.\n\n#### Essentials\n\n* **[Using dependencies][using-dependencies-article]**:\n  Learn how to use the dependencies that are registered with the library.\n\n* **[Registering dependencies][registering-dependencies-article]**:\n  Learn how to register your own dependencies with the library so that they immediately become\n  available from any part of your code base.\n\n* **[Live, preview, and test dependencies][live-preview-test-article]**:\n  Learn how to provide different implementations of your dependencies for use in the live\n  application, as well as in Xcode previews, and even in tests.\n\n* **[Testing][testing-article]**:\n  One of the main reasons to control dependencies is to allow for easier testing. Learn some tips\n  and tricks for writing better tests with the library.\n\n#### Advanced\n\n* **[Designing dependencies][designing-dependencies-article]**:\n  Learn techniques on designing your dependencies so that they are most flexible for injecting into\n  features and overriding for tests.\n  \n* **[Overriding dependencies][overriding-dependencies-article]**:\n  Learn how dependencies can be changed at runtime so that certain parts of your application can use\n  different dependencies.\n\n* **[Dependency lifetimes][lifetimes-article]**:\n  Learn about the lifetimes of dependencies, how to prolong the lifetime of a dependency, and how\n  dependencies are inherited.\n\n* **[Single entry point systems][single-entry-point-systems-article]**:\n  Learn about \"single entry point\" systems, and why they are best suited for this dependencies\n  library, although it is possible to use the library with non-single entry point systems.\n\n## Examples\n\nWe rebuilt Apple's [Scrumdinger][scrumdinger] demo application using modern, best practices for\nSwiftUI development, including using this library to control dependencies on file system access,\ntimers and speech recognition APIs. That demo can be found [here][syncups-demo].\n\n## Documentation\n\nThe latest documentation for the Dependencies APIs is available [here][docs].\n\n## Installation\n\nYou can add Dependencies to an Xcode project by adding it to your project as a package.\n\n\u003e https://github.com/pointfreeco/swift-dependencies\n\nIf you want to use Dependencies in a [SwiftPM](https://swift.org/package-manager/) project, it's as\nsimple as adding it to your `Package.swift`:\n\n``` swift\ndependencies: [\n  .package(url: \"https://github.com/pointfreeco/swift-dependencies\", from: \"1.0.0\")\n]\n```\n\nAnd then adding the product to any target that needs access to the library:\n\n```swift\n.product(name: \"Dependencies\", package: \"swift-dependencies\"),\n```\n\n## Community\n\nIf you want to discuss this library or have a question about how to use it to solve \na particular problem, there are a number of places you can discuss with fellow \n[Point-Free](http://www.pointfree.co) enthusiasts:\n\n* For long-form discussions, we recommend the\n  [discussions](http://github.com/pointfreeco/swift-dependencies/discussions) tab of this repo.\n* For casual chat, we recommend the [Point-Free Community Slack](http://pointfree.co/slack-invite).\n\n## Extensions\n\nThis library controls a number of dependencies out of the box, but is also open to extension. The\nfollowing projects all build on top of Dependencies:\n\n  * [Dependencies Additions](https://github.com/tgrapperon/swift-dependencies-additions): A\n    companion library that provides higher-level dependencies.\n  * [Dependencies Protocol Extras](https://github.com/arasan01/swift-dependencies-extras): A library\n    to make swift-dependencies even more useful when using protocols.\n\n## Alternatives\n\nThere are many other dependency injection libraries in the Swift community. Each has its own set of\npriorities and trade-offs that differ from Dependencies. Here are a few well-known examples:\n\n  * [Factory](https://github.com/hmlongco/Factory)\n  * [Needle](https://github.com/uber/needle)\n  * [Swinject](https://github.com/Swinject/Swinject)\n  * [Weaver](https://github.com/scribd/Weaver)\n\n## License\n\nThis library is released under the MIT license. See [LICENSE](LICENSE) for details.\n\n[docs]: https://swiftpackageindex.com/pointfreeco/swift-dependencies/main/documentation/dependencies\n[concurrency-support-article]: https://swiftpackageindex.com/pointfreeco/swift-dependencies/main/documentation/dependencies/concurrencysupport\n[designing-dependencies-article]: https://swiftpackageindex.com/pointfreeco/swift-dependencies/main/documentation/dependencies/designingdependencies\n[lifetimes-article]: https://swiftpackageindex.com/pointfreeco/swift-dependencies/main/documentation/dependencies/lifetimes\n[live-preview-test-article]: https://swiftpackageindex.com/pointfreeco/swift-dependencies/main/documentation/dependencies/livepreviewtest\n[testing-article]: https://swiftpackageindex.com/pointfreeco/swift-dependencies/main/documentation/dependencies/testing\n[overriding-dependencies-article]: https://swiftpackageindex.com/pointfreeco/swift-dependencies/main/documentation/dependencies/overridingdependencies\n[registering-dependencies-article]: https://swiftpackageindex.com/pointfreeco/swift-dependencies/main/documentation/dependencies/registeringdependencies\n[single-entry-point-systems-article]: https://swiftpackageindex.com/pointfreeco/swift-dependencies/main/documentation/dependencies/singleentrypointsystems\n[using-dependencies-article]: https://swiftpackageindex.com/pointfreeco/swift-dependencies/main/documentation/dependencies/usingdependencies\n[what-are-dependencies-article]: https://swiftpackageindex.com/pointfreeco/swift-dependencies/main/documentation/dependencies/whataredependencies\n[quick-start-article]: https://swiftpackageindex.com/pointfreeco/swift-dependencies/main/documentation/dependencies/quickstart\n[registering-dependencies-article]: https://swiftpackageindex.com/pointfreeco/swift-dependencies/main/documentation/dependencies/registeringdependencies \n[scrumdinger]: https://developer.apple.com/tutorials/app-dev-training/getting-started-with-scrumdinger\n[syncups-demo]: https://github.com/pointfreeco/syncups\n[swiftui-nav-gh]: http://github.com/pointfreeco/swiftui-navigation\n[dep-values-docs]: https://swiftpackageindex.com/pointfreeco/swift-dependencies/main/documentation/dependencies/dependencyvalues#dependency-values\n[withdependencies-docs]: https://swiftpackageindex.com/pointfreeco/swift-dependencies/main/documentation/dependencies/withdependencies(isolation:_:operation:)\n[immediate-clock-docs]: https://pointfreeco.github.io/swift-clocks/main/documentation/clocks/immediateclock\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpointfreeco%2Fswift-dependencies","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpointfreeco%2Fswift-dependencies","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpointfreeco%2Fswift-dependencies/lists"}