{"id":15132513,"url":"https://github.com/square/cleanse","last_synced_at":"2025-09-29T00:32:27.766Z","repository":{"id":9167545,"uuid":"60655833","full_name":"square/Cleanse","owner":"square","description":"Lightweight Swift Dependency Injection Framework","archived":true,"fork":false,"pushed_at":"2024-06-13T18:34:47.000Z","size":3368,"stargazers_count":1781,"open_issues_count":0,"forks_count":83,"subscribers_count":50,"default_branch":"master","last_synced_at":"2025-09-06T08:19:31.732Z","etag":null,"topics":["dependency-injection","ios","swift"],"latest_commit_sha":null,"homepage":null,"language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/square.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGELOG.md","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":"2016-06-08T00:24:36.000Z","updated_at":"2025-08-27T18:23:31.000Z","dependencies_parsed_at":"2024-06-18T17:11:05.095Z","dependency_job_id":null,"html_url":"https://github.com/square/Cleanse","commit_stats":{"total_commits":212,"total_committers":21,"mean_commits":"10.095238095238095","dds":0.5801886792452831,"last_synced_commit":"9aacffc5668171bb3492816797c177842d80007c"},"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/square/Cleanse","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/square%2FCleanse","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/square%2FCleanse/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/square%2FCleanse/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/square%2FCleanse/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/square","download_url":"https://codeload.github.com/square/Cleanse/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/square%2FCleanse/sbom","scorecard":{"id":843133,"data":{"date":"2025-08-11","repo":{"name":"github.com/square/Cleanse","commit":"ad53ff66244350df042c4ffb15eb9a85462bdae8"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.1,"checks":[{"name":"Maintained","score":0,"reason":"project is archived","details":["Warn: Repository is archived."],"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/main.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":2,"reason":"Found 4/15 approved changesets -- score normalized to 2","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: third-party GitHubAction not pinned by hash: .github/workflows/main.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/square/Cleanse/main.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/square/Cleanse/main.yml/master?enable=pin","Info:   0 out of   1 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":9,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Warn: project license file does not contain an FSF or OSI license."],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact 4.2.6 not signed: https://api.github.com/repos/square/Cleanse/releases/30531661","Warn: release artifact 4.2.6 does not have provenance: https://api.github.com/repos/square/Cleanse/releases/30531661"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":5,"reason":"5 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-j6gc-792m-qgm2","Warn: Project is vulnerable to: GHSA-pj73-v5mw-pm9j","Warn: Project is vulnerable to: GHSA-7627-mp87-jf6q","Warn: Project is vulnerable to: GHSA-g397-v4w5-4m79","Warn: Project is vulnerable to: GHSA-5cm2-9h8c-rvfx"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 27 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-23T20:54:12.852Z","repository_id":9167545,"created_at":"2025-08-23T20:54:12.852Z","updated_at":"2025-08-23T20:54:12.852Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":277450939,"owners_count":25819971,"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","status":"online","status_checked_at":"2025-09-28T02:00:08.834Z","response_time":79,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["dependency-injection","ios","swift"],"created_at":"2024-09-26T04:20:22.387Z","updated_at":"2025-09-29T00:32:27.185Z","avatar_url":"https://github.com/square.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"[Deprecated] Cleanse - Swift Dependency Injection\n====================================\n\n.. image:: Documentation/cleanse_logo_small.png\n  :align: right\n\n\n.. image:: https://travis-ci.org/square/Cleanse.svg?branch=master\n  :target: https://travis-ci.org/square/Cleanse\n\n.. image:: https://coveralls.io/repos/github/square/Cleanse/badge.svg?branch=master\u0026asdf\n  :target: https://coveralls.io/github/square/Cleanse?branch=master\n\n\nCleanse is a `dependency injection`_ framework for Swift. It is designed from the ground-up with *developer experience*\nin mind. It takes inspiration from both `Dagger`_ and `Guice`_.\n\n.. _dependency injection: https://en.wikipedia.org/wiki/Dependency_injection\n.. _Guice: https://github.com/google/guice\n.. _Dagger: http://google.github.io/dagger/\n\nDeprecation Notice:\n-------------------\n\nDear Cleanse Community,\n\n**We are announcing that the Cleanse repository will be officially deprecated as of June 13th, 2024.** Over the years, Cleanse has aimed to provide a robust solution for Swift dependency injection, and we are incredibly grateful for the support and contributions from our community.\n\nThis decision is based on Square's decision to use a different dependency injection framework. We believe this step will allow us to focus our efforts on other projects and innovations that better serve the needs of our users and the broader open-source ecosystem.\n\nWhat This Means for You\n````````````\n- **No Further Updates**: There will be no further updates, bug fixes, or new features added to Cleanse.\n- **Repository Status**: The repository will remain available in a read-only state for historical reference and for those who may still find value in the existing codebase.\n- **Support**: We will no longer provide active support or respond to issues and pull requests.\n\nRecommended Alternatives\n````````````\nWe encourage you to fork this repo, or explore the following alternatives that may better meet your needs:\n\n- `Needle`_\n- `Swinject`_\n- `Weaver`_\n- `Factory`_\n- `PointFree's Dependencies`_\n\n.. _Needle: https://github.com/uber/needle\n.. _Swinject: https://github.com/Swinject/Swinject\n.. _Weaver: https://github.com/scribd/Weaver\n.. _Factory: https://github.com/hmlongco/Factory\n.. _PointFree's Dependencies: https://github.com/pointfreeco/swift-dependencies\n\nContact us\n``````````\nIf you have interest in maintaining this repo, or have any other inquiries, please reach out to us at opensource+external@squareup.com.\n\nThank You\n````````````\nWe extend our heartfelt thanks to everyone who has contributed to Cleanse, whether through code, documentation, or community support. Your efforts have been invaluable and deeply appreciated. Thank you for being a part of the Cleanse journey.\n\nSincerely,\nThe Cleanse Team at Square\n\nGetting Started\n---------------\nThis is a quick guide on how to get started using Cleanse in your application.\n\nA full-fledged example of using Cleanse with Cocoa Touch can be found in ``Examples/CleanseGithubBrowser``\n\nInstallation\n````````````\nUsing `CocoaPods`_\n~~~~~~~~~~~~~~~~~~~\nYou can pull in the latest Cleanse version into your ``Podfile`` using\n\n``pod 'Cleanse'``\n\n.. _CocoaPods: https://github.com/cocoapods/cocoapods/\n\nUsing Xcode\n~~~~~~~~~~~\n``Cleanse.xcodeproj`` can be dragged and dropped into an existing project or workspace in Xcode.\nOne may add ``Cleanse.framework`` as a target dependency and embed it.\n\nUsing `Carthage`_\n~~~~~~~~~~~~~~~~~\nCleanse should be able to be configured with `Carthage`_. One should be able to follow the\n`Adding Frameworks to an Application`_ from `Carthage's README`_ to successfully do this.\n\n.. _Adding Frameworks to an Application: https://github.com/Carthage/Carthage#adding-frameworks-to-an-application\n.. _Carthage's README: https://github.com/Carthage/Carthage/blob/master/README.md\n.. _Carthage: https://github.com/Carthage/Carthage/\n\nUsing `Swift Package Manager`_\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nCleanse can be used with `Swift Package Manager`_. The following a definition that can be added to the dependencies \nof a ``Project`` declaration. Adding `Cleanse` as a package dependency in Xcode 11 is supported by v4.2.5 and above.\n\n.. _Swift Package Manager: https://github.com/apple/swift-package-manager\n\nFeatures\n--------\n=================================== =================================\n   Feature                          Cleanse Implementation Status\n=================================== =================================\nMulti-Bindings                      Supported (``.intoCollection()``)\nOverrides                           Supported\nObjective-C Compatibility layer     Supported\nProperty Injection [#pinj]_         Supported\nType Qualifiers                     Supported via `Type Tags`_\n`Assisted Injection`_               Supported\n`Subcomponents`_                    Supported via `Components`_\n`Service Provider Interface`_       Supported\n`cleansec`_ (Cleanse Compiler)      Experimental\n=================================== =================================\n\n.. [#pinj] Property injection is known as `field injection`_ in other DI frameworks\n\n.. _Subcomponents: http://google.github.io/dagger/subcomponents.html\n.. _cleansec: https://github.com/square/Cleanse/tree/master/cleansec\n.. _field injection: https://github.com/google/guice/wiki/Injections#field-injection\n\nAnother very important part of a DI framework is how it handles errors. Failing fast is ideal. Cleanse is designed to\nsupport fast failure. It currently supports fast failing for some of the more common errors, but it isn't complete\n\n=================================== =================================\n   Error Type                       Cleanse Implementation Status\n=================================== =================================\nMissing Providers                   Supported [#f1]_\nDuplicate Bindings                  Supported\nCycle Detection                     Supported\n=================================== =================================\n\n.. [#f1] When a provider is missing, errors present line numbers, etc. where the provider was required. Cleanse\n        will also collect all errors before failing\n\nUsing Cleanse\n`````````````\nThe Cleanse API is in a Swift module called ``Cleanse`` (surprised?). To use any of its API in a file, at the top,\none must import it.\n\n.. code-block:: swift\n\n  import Cleanse\n\nDefining a Component and Root Type\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nCleanse is responsible for building a graph (or more specifically a `directed acyclic graph`_) that represents all of your dependencies.\nThis graph starts with a root object which is connected to its immediate dependencies, and those dependencies hold edges to its dependencies and so on until we have a complete picture of your application's object graph.\n\n.. _`directed acyclic graph`: https://en.wikipedia.org/wiki/Directed_acyclic_graph\n\nThe entry point into managing your dependencies with Cleanse starts by defining a \"Root\" object that is returned to you upon construction. In a Cocoa Touch application, our root object could be the ``rootViewController`` object we set on the application's ``UIWindow``. *(More logically the root object is the App Delegate, however since we don't control construction of that we would have to use Property Injection. You can read more about this in the* `Advanced Setup`_ *guide)*\n\nLet's begin by defining the ``RootComponent``:\n\n\n.. code-block:: swift\n\n  struct Component : Cleanse.RootComponent {\n      // When we call build(()) it will return the Root type, which is a RootViewController instance.\n      typealias Root = RootViewController\n\n      // Required function from Cleanse.RootComponent protocol.\n      static func configureRoot(binder bind: ReceiptBinder\u003cRootViewController\u003e) -\u003e BindingReceipt\u003cRootViewController\u003e {\n\n      }\n\n      // Required function from Cleanse.RootComponent protocol.\n      static func configure(binder: Binder\u003cUnscoped\u003e) {\n          // We will fill out contents later.\n      }\n  }\n\nAfter creating our root component, we find that we're required to implement two functions:\n``static func configureRoot(binder bind: ReceiptBinder\u003cRootViewController\u003e) -\u003e BindingReceipt\u003cRootViewController\u003e`` and ``static func configure(binder: Binder\u003cUnscoped\u003e)``. These functions are very important because they will contain the logic for how we construct every object/dependency in our app. The parameters and return types are confusing right now, but will make more sense as we go along.\n\nThe first function is required of any `Component` since it tells Cleanse how to construct the root object. Let's fill in the contents to configure how we will construct our ``RootViewController``.\n\n.. code-block:: swift\n\n  static func configureRoot(binder bind: ReceiptBinder\u003cRootViewController\u003e) -\u003e BindingReceipt\u003cRootViewController\u003e {\n      return bind.to(factory: RootViewController.init)\n  }\n\n\nNow, let's create our ``RootViewController`` class\n\n.. code-block:: swift\n\n  class RootViewController: UIViewController {\n      init() {\n          super.init(nibName: nil, bundle: nil)\n      }\n\n      required init?(coder aDecoder: NSCoder) {\n          fatalError(\"init(coder:) has not been implemented\")\n      }\n\n      override func viewDidLoad() {\n          super.viewDidLoad()\n          self.view.backgroundColor = .blue\n      }\n  }\n\n\nWe've successfully wired up our root component! Our root object ``RootViewController`` is configured properly, so in our App Delegate we can now `build` the component (and graph) to use it.\n\n**Important**: It is important that you retain an instance of the `ComponentFactory\u003cE\u003e` returned from `ComponentFactory.of(:)`. Otherwise subcomponents may unexpectedly become deallocated.\n\n.. code-block:: swift\n\n    // IMPORTANT: We must retain an instance of our `ComponentFactory`.\n    @UIApplicationMain\n    class AppDelegate: UIResponder, UIApplicationDelegate {\n        var factory: ComponentFactory\u003cAppDelegate.Component\u003e?\n\n        func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -\u003e  Bool {\n            // Build our root object in our graph.\n            factory = try! ComponentFactory.of(AppDelegate.Component.self)\n            let rootViewController = factory!.build(())\n\n            // Now we can use the root object in our app.\n            window!.rootViewController = rootViewController\n            window!.makeKeyAndVisible()\n\n            return true\n        }\n\nSatisfying Dependencies\n~~~~~~~~~~~~~~~~~~~~~~~\n\nRunning the app will now display our ``RootViewController`` with a blue background. However this is not very interesting nor realistic as our ``RootViewController`` will likely require many dependencies to set up our app. So let's create a simple dependency ``RootViewProperties`` that will hold the background color of our root view (among other future properties).\n\n.. code-block:: swift\n\n  struct RootViewProperties {\n      let backgroundColor: UIColor\n  }\n\nAnd then inject ``RootViewProperties`` into our ``RootViewContoller`` and set the background color.\n\n.. code-block:: swift\n\n  class RootViewController: UIViewController {\n      let rootViewProperties: RootViewProperties\n      init(rootViewProperties: RootViewProperties) {\n          self.rootViewProperties = rootViewProperties\n          super.init(nibName: nil, bundle: nil)\n      }\n\n      required init?(coder aDecoder: NSCoder) {\n          fatalError(\"init(coder:) has not been implemented\")\n      }\n\n      override func viewDidLoad() {\n          super.viewDidLoad()\n\n          self.view.backgroundColor = rootViewProperties.backgroundColor\n      }\n  }\n\n\nRunning the app now will yield a new error saying a provider for ``RootViewProperties`` is missing. That's because we referenced it from our ``RootViewController`` class, but Cleanse didn't find a binding for the ``RootViewProperties`` type. So let's create one! We will do this inside the ``static func configure(binder: Binder\u003cUnscoped\u003e)`` function we talked about earlier inside our root component.\n\n.. code-block:: swift\n\n  static func configure(binder: Binder\u003cUnscoped\u003e) {\n        binder\n            .bind(RootViewProperties.self)\n            .to { () -\u003e RootViewProperties in\n                RootViewProperties(backgroundColor: .blue)\n            }\n    }\n\nNow that we have satisfied the ``RootViewProperties`` dependency, we should be able to successfully launch and see the same blue background as before.\n\nAs the functionality of this app grows, one may add more dependencies to ``RootViewController`` as well as more Modules_ to satisfy them.\n\nIt may be worth taking a look at our `example app`_ to see a more full-featured example.\n\n.. _example app: https://github.com/square/Cleanse/tree/master/Examples/CleanseGithubBrowser\n\nCore Concepts \u0026 Data Types\n--------------------------\n\n``Provider``\\ /\\ ``ProviderProtocol``\n`````````````````````````````````````\n\nWraps a value of its containing type. Serves the same functionality as Java's `javax.inject.Provider`_.\n\n``Provider`` and ``TaggedProvider`` (see below) implement ``ProviderProtocol`` protocol which is defined as:\n\n.. code-block:: swift\n\n    public protocol ProviderProtocol {\n        associatedtype Element\n        func get() -\u003e Element\n    }\n\n.. _javax.inject.Provider: http://docs.oracle.com/javaee/6/api/javax/inject/Provider.html\n\nType Tags\n`````````\n\nIn a given component, there may be the desire to provide or require different instances of common types with different\nsignificances. Perhaps we need to distinguish the base URL of our API server from the URL of our temp directory.\n\nIn Java, this is done with annotations, in particular ones annotated with `@Qualifier`_. In Go, this can be accomplished\nwith `tags on structs`_ of fields.\n\n.. _@Qualifier:  https://docs.oracle.com/javaee/6/api/javax/inject/Qualifier.html\n.. _tags on structs: https://golang.org/pkg/reflect/#StructTag\n\nIn Cleanse's system a type annotation is equivalent to an implementation of the Tag protocol:\n\n.. code-block:: swift\n\n    public protocol Tag {\n        associatedtype Element\n    }\n\nThe `associatedtype`_, ``Element``, indicates what type the tag is valid to apply to. This is very different than annotations\nin Java used as qualifiers in Dagger and Guice which cannot be constrained by which type they apply to.\n\nIn Cleanse, the ``Tag`` protocol is implemented to distinguish a type, and the ``TaggedProvider`` is used to wrap a value of\n``Tag.Element``. Since most of the library refers to ``ProviderProtocol``, ``TaggedProvider`` is accepted almost everywhere a\n``Provider`` is.\n\nIts definition is almost identical to ``Provider`` aside from an additional generic argument:\n\n.. code-block:: swift\n\n    struct TaggedProvider\u003cTag : Cleanse.Tag\u003e : ProviderProtocol {\n        func get() -\u003e Tag.Element\n    }\n\nExample\n~~~~~~~\n\nSay one wanted to indicate a URL type, perhaps the base URL for the API endpoints, one could define a tag this way:\n\n.. code-block:: swift\n\n    public struct PrimaryAPIURL : Tag {\n        typealias Element = NSURL\n    }\n\nThen one may be able to request a ``TaggedProvider`` of this special URL by using the type:\n\n.. code-block:: swift\n\n    TaggedProvider\u003cPrimaryAPIURL\u003e\n\nIf we had a class that requires this URL to perform a function, the constructor could be defined like:\n\n\n.. code-block:: swift\n\n    class SomethingThatDoesAnAPICall {\n        let primaryURL: NSURL\n        init(primaryURL: TaggedProvider\u003cPrimaryAPIURL\u003e) {\n            self.primaryURL = primaryURL.get()\n        }\n    }\n\n\nModules\n```````\n\nModules in Cleanse serve a similar purpose to Modules in other DI systems such as Dagger or Guice.\nModules are building blocks for one's object graph. Using modules in Cleanse may look very similar to those\nfamiliar with Guice since configuration is done at runtime and the binding DSL is very inspired by Guice's.\n\nThe ``Module`` protocol has a single method, ``configure(binder:)``, and is is defined as:\n\n.. code-block:: swift\n\n    protocol Module {\n        func configure\u003cB : Binder\u003e(binder: B)\n    }\n\nExamples\n~~~~~~~~\n\nProviding the Base API URL\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\n.. code-block:: swift\n\n    struct PrimaryAPIURLModule : Module {\n      func configure(binder: Binder\u003cUnscoped\u003e) {\n        binder\n          .bind(NSURL.self)\n          .tagged(with: PrimaryAPIURL.self)\n          .to(value: NSURL(string: \"https://connect.squareup.com/v2/\")!)\n      }\n    }\n\nConsuming the Primary API URL (e.g. \"https://connect.squareup.com/v2/\")\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\n**Note**: It is generally a good practice to embed the ``Module`` that configures X as an inner struct of X named ``Module``. To disambiguate Cleanse's Module protocol from the inner struct being defined, one has to qualify the protocol with ``Cleanse.Module``\n\n\n.. code-block:: swift\n\n    class SomethingThatDoesAnAPICall {\n        let primaryURL: NSURL\n        init(primaryURL: TaggedProvider\u003cPrimaryAPIURL\u003e) {\n            self.primaryURL = primaryURL.get()\n        }\n        struct Module : Cleanse.Module {\n            func configure(binder: Binder\u003cUnscoped\u003e) {\n                binder\n                    .bind(SomethingThatDoesAnAPICall.self)\n                    .to(factory: SomethingThatDoesAnAPICall.init)\n            }\n        }\n    }\n\nComponents\n`````````````````````\nCleanse has a concept of a ``Component``. A ``Component`` represents an object graph of our dependencies that returns the ``Root`` `associated type`_ upon construction and is used as the \"entry point\" into Cleanse. However, we can also use a ``Component`` to create a subgraph inside our parent object graph, called a subcomponent. Subcomponents are closely related to scopes_ and are used to scope your dependencies. Objects inside a component are only allowed to inject dependencies that exist within the same component (or scope), or an ancestor's component. A parent component is not allowed to reach into a subcomponent and retrieve a dependency. One example of using components to scope dependencies is by having a ``LoggedInComponent`` inherting from your application's Root component. This allows you to bind logged in specific objects such as session tokens or account objects within the ``LoggedInComponent`` so that you can't accidently leak these dependencies into objects used outside of a logged session (i.e welcome flow views).\n\nThe base component protocol is defined as:\n\n.. code-block:: swift\n\n    public protocol ComponentBase {\n      /// This is the binding required to construct a new Component. Think of it as somewhat of an initialization value.\n      associatedtype Seed = Void\n\n      /// This should be set to the root type of object that is created.\n      associatedtype Root\n\n      associatedtype Scope: Cleanse._ScopeBase = Unscoped\n\n      static func configure(binder: Binder\u003cSelf.Scope\u003e)\n\n      static func configureRoot(binder bind: ReceiptBinder\u003cRoot\u003e) -\u003e BindingReceipt\u003cRoot\u003e\n    }\n\n\nThe outermost component of an object graph (e.g. the Root component), is built by the ``build(())`` method on `ComponentFactory`.\nThis is defined as the following protocol extension:\n\n.. code-block:: swift\n\n    public extension Component {\n        /// Builds the component and returns the root object.\n        public func build() throws -\u003e Self.Root\n    }\n\nExamples\n~~~~~~~~\n\nDefining a subcomponent\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\n.. code-block:: swift\n\n    struct RootAPI {\n        let somethingUsingTheAPI: SomethingThatDoesAnAPICall\n    }\n\n    struct APIComponent : Component {\n        typealias Root = RootAPI\n        func configure(binder: Binder\u003cUnscoped\u003e) {\n            // \"include\" the modules that create the component\n            binder.include(module: PrimaryAPIURLModule.self)\n            binder.include(module: SomethingThatDoesAnAPICall.Module.self)\n            // bind our root Object\n            binder\n                .bind(RootAPI.self)\n                .to(factory: RootAPI.init)\n        }\n    }\n\nUsing the component\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\nCleanse will automatically create the type ``ComponentFactory\u003cAPIComponent\u003e`` in your object graph by calling ``binder.install(dependency: APIComponent.self)``.\n\n.. code-block:: swift\n\n  struct Root : RootComponent {\n      func configure(binder: Binder\u003cUnscoped\u003e) {\n          binder.install(dependency: APIComponent.self)\n      }\n      // ...\n  }\n\n\nAnd then you can use it by injecting in the ``ComponentFactory\u003cAPIComponent\u003e`` instance into an object and calling ``build(())``.\n\n.. code-block:: swift\n\n  class RootViewController: UIViewController {\n      let loggedInComponent: ComponentFactory\u003cAPIComponent\u003e\n\n      init(loggedInComponent: ComponentFactory\u003cAPIComponent\u003e) {\n          self.loggedInComponent = loggedInComponent\n          super.init(nibName: nil, bundle: nil)\n      }\n\n      func logIn() {\n          let apiRoot = loggedInComponent.build(())\n      }\n  }\n\nAssisted Injection\n``````````````````\nSummary (`RFC #112`_)\n~~~~~~~~~~~~~~~~~~~~~\n\n.. _RFC #112: https://github.com/square/Cleanse/issues/112\n\n\nAssisted injection is used when combining seeded parameters and pre-bound dependencies. Similar to how a subcomponent has a ``Seed`` that is used to build the object graph, assisted injection allows you to eliminate boilerplate by creating a ``Factory`` type with a defined ``Seed`` object for construction via the ``build(_:)`` function.\n\nExamples\n~~~~~~~~\n\nCreating a factory\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\nSay we have a detail view controller that displays a particular customer's information based on the user's selection from a list view controller.\n\n.. code-block:: swift\n\n  class CustomerDetailViewController: UIViewController {\n      let customerID: String\n      let customerService: CustomerService\n      init(customerID: Assisted\u003cString\u003e, customerService: CustomerService) {\n          self.customerID = customerID.get()\n          self.customerService = customerService\n      }\n      ...\n  }\n\nIn our initializer, we have ``Assisted\u003cString\u003e`` which represents an assisted injection parameter based on the customer ID selected from the list view controller, and a pre-bound dependency ``CustomerService``.\n\nIn order to create our factory, we need to define a type that conforms to ``AssistedFactory`` to set our ``Seed`` and ``Element`` types.\n\n.. code-block:: swift\n\n  extension CustomerDetailViewController {\n      struct Seed: AssistedFactory {\n          typealias Seed = String\n          typealias Element = CustomerDetailViewController\n      }\n  }\n\nOnce we create our ``AssistedFactory`` object, we can create the factory binding through Cleanse.\n\n.. code-block:: swift\n\n  extension CustomerDetailViewController {\n      struct Module: Cleanse.Module {\n          static func configure(binder: Binder\u003cUnscoped\u003e) {\n              binder\n                .bindFactory(CustomerDetailViewController.self)\n                .with(AssistedFactory.self)\n                .to(factory: CustomerDetailViewController.init)\n          }\n      }\n  }\n\nConsuming our factory\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\nAfter creating our binding, Cleanse will bind a ``Factory\u003cCustomerDetailViewController.AssistedFactory\u003e`` type into our object graph. So in our customer list view controller, consuming this factory may look like:\n\n.. code-block:: swift\n\n    class CustomerListViewController: UIViewController {\n        let detailViewControllerFactory: Factory\u003cCustomerDetailViewController.AssistedFactory\u003e\n\n        init(detailViewControllerFactory: Factory\u003cCustomerDetailViewController.AssistedFactory\u003e) {\n            self.detailViewControllerFactory = detailViewControllerFactory\n        }\n        ...\n\n        func tappedCustomer(with customerID: String) {\n            let detailVC = detailViewControllerFactory.build(customerID)\n            self.present(detailVC, animated: false)\n        }\n    }\n\nService Provider Interface\n``````````````````````````\nSummary (`RFC #118`_)\n~~~~~~~~~~~~~~~~~~~~~\n\n.. _RFC #118: https://github.com/square/Cleanse/issues/118\n\nCleanse provides a plugin interface that developers can use to hook into the generated object graph to create custom validations and tooling.\n\nCreating a plugin can be done in 3 steps:\n\n**1. Create your plugin implementation by conforming to the protocol** ``CleanseBindingPlugin``\n\nYou will be required to implement the function ``func visit(root: ComponentBinding, errorReporter:\nCleanseErrorReporter)``, which hands you an instance of a ``ComponentBinding`` and\n``CleanseErrorReporter``.\n\nThe first parameter, ``ComponentBinding``, is a representation of the root component and can be used\nto traverse the entire object graph. The second, ``CleanseErrorReporter`` is used to report\nerrors back to the user after validation is complete.\n\n**2. Register your plugin with a** ``CleanseServiceLoader`` **instance**\n\nAfter creating an instance of a ``CleanseServiceLoader``, you can register your plugin via the\n``register(_:)`` function.\n\n**3. Pass your service loader into the** ``RootComponent`` **factory function**\n\nThe ``RootComponent`` factory function, ``public static func of(_:validate:serviceLoader:)`` accepts\na ``CleanseServiceLoader`` instance and will run all the plugins registered within that object.\n\n**NOTE**: Your plugins will only be run if you set `validate` to `true` in the factory function.\n\nSample plugin implementations are available in the RFC linked above.\n\nBinder\n``````\nA ``Binder`` instance is what is passed to ``Module.configure(binder:)`` which module implementations use to configure\ntheir providers.\n\nBinders have two core methods that one will generally interface with. The first, and simpler one, is the install method.\nOne passes it an instance of a module to be installed.  It is used like:\n\n.. code-block:: swift\n\n  binder.include(module: PrimaryAPIURLModule.self)\n\nIt essentially tells the binder to call ``configure(binder:)`` on ``PrimaryAPIURLModule``.\n\nThe other core method that binders expose is the ``bind\u003cE\u003e(type: E.Type)``. This is the entry point to configure a\nbinding. The bind methods takes one argument, which the `metattype`_ of the element being configured. ``bind()``\nreturns a ``BindingBuilder`` that one must call methods on to complete the configuration of the binding that was\ninitiated.\n\n``bind()`` and subsequent builder methods that are not *terminating* are annotated with ``@warn_unused_result``\nto prevent errors by only partially configuring a binding.\n\n.. _metattype: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Types.html#//apple_ref/swift/grammar/metatype-type\n\n\nThe ``type`` argument of ``bind()`` has a default and can be inferred and omitted in some common cases. In this documentation we sometimes specify it explicitly to improve readability.\n\n\n``BindingBuilder`` and Configuring Your Bindings\n````````````````````````````````````````````````\n\nThe BindingBuilder is a fluent API for configuring your bindings. It is built in a way that guides one through the\nprocess of configuring a binding through code completion. A simplified grammar for the DSL of ``BindingBuilder`` is::\n\n  binder\n    .bind([Element.self])                // Bind Step\n   [.tagged(with: Tag_For_Element.self)] // Tag step\n   [.sharedInScope()]                    // Scope step\n   {.to(provider:) |                     // Terminating step\n    .to(factory:)  |\n    .to(value:)}\n\nBind Step\n~~~~~~~~~\nThis starts the binding process to define how an instance of ``Element`` is created\n\nTag Step (Optional)\n~~~~~~~~~~~~~~~~~~~\nAn optional step that indicates that the provided type should actually be\n``TaggedProvider\u003cElement\u003e`` and not just ``Provider\u003cElement\u003e``.\n\nSee: `Type Tags`_ for more information\n\n.. _scopes:\n\nScope Step\n~~~~~~~~~~~~~~~~~~~~~\n\nBy default, whenever an object is requested, Cleanse constructs a new one.\nIf the optional `.sharedInScope()` is specified, Cleanse will memoize and return the same instance in the scope of the ``Component`` it was configured in. Each ``Component`` requires its own `Scope` type. So if this is configured as a singleton in the `RootComponent`, then will return the same instance for the entire app.\n\nCleanse provides two scopes for you: ``Unscoped`` and ``Singleton``. ``Unscoped`` is the default scope that will always construct a new object, and ``Singleton`` is provided out of convenience but not necessary to use. It is most commonly used as the scope type for your application's ``RootComponent``.\n\n\nTerminating Step\n~~~~~~~~~~~~~~~~\n\nTo finish configuring a binding, one *must* invoke one of the terminating methods on ``BindingBuilder``.\nThere are multiple methods that are considered terminating steps. The common ones are described below.\n\nDependency-Free Terminating methods\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\nThis is a category of terminating methods that configure how to instantiate elements that don't have dependencies\non other instances configured in the object graph.\n\nTerminating Method: ``to(provider: Provider\u003cE\u003e)``\n#################################################\nOther terminating methods funnel into this. If the binding of ``Element`` is terminated with this variant,\n``.get()`` will be invoked on the on the provider argument when an instance of ``Element`` is requested.\n\nTerminating Method: ``to(value: E)``\n####################################\nThis is a convenience method. It is semantically equivalent to\n``.to(provider: Provider(value: value))`` or ``.to(factory: { value })``. It may\noffer performance advantages in the future, but currently doesn't.\n\nTerminating Method: ``to(factory: () -\u003e E)`` *(0th arity)*\n##########################################################\nThis takes a closure instead of a provider, but is otherwise equivalent. Is equivalent to ``.to(provider: Provider(getter: factory))``\n\n\nDependency-Requesting Terminating Methods\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\nThis is how we define requirements for bindings.\n`Dagger 2`_ determines requirements at compile time by looking at the arguments of ``@Provides`` methods and ``@Inject`` constructors.\n`Guice`_ does something similar, but using reflection to determine arguments.\nOne can explicitly request a dependency from Guice's binder via the `getProvider()`_ method.\n\n.. _getProvider(): https://google.github.io/guice/api-docs/latest/javadoc/com/google/inject/Binder.html#getProvider-java.lang.Class-\n.. _Dagger 2: https://google.github.io/dagger/\n\nUnlike Java, Swift doesn't have annotation processors to do this at compile time, nor does it have a `stable` reflection\nAPI. We also don't want to expose a `getProvider()`_-like method since it allows one to do dangerous things and\nalso one loses important information on which providers depend on other providers.\n\nSwift does, however, have a very powerful generic system. We leverage this to provide safety and simplicity when\ncreating our bindings.\n\nTerminating Methods: ``to\u003cP1\u003e(factory: (P1) -\u003e E)`` *(1st arity)*\n#################################################################\n\nThis registers a binding of E to the factory function which takes one argument.\n\n.. admonition:: How it works\n\n  Say we have a hamburger defined as:\n\n  .. code-block:: swift\n\n     struct Hamburger {\n        let topping: Topping\n        // Note: this actually would be created implicitly for structs\n        init(topping: Topping) {\n          self.topping = topping\n        }\n      }\n\n  When one references the initializer without calling it (e.g. ``let factory = Hamburger.init``),\n  the expression results in a `function type`_ of\n\n  .. code-block:: swift\n\n     (topping: Topping) -\u003e Hamburger\n\n  So when configuring its creation in a module, calling\n\n  .. code-block:: swift\n\n     binder.bind(Hamburger.self).to(factory: Hamburger.init)\n\n  will result in calling the ``.to\u003cP1\u003e(factory: (P1) -\u003e E)`` terminating function and resolve ``Element``\n  to ``Hamburger`` and ``P1`` to ``Topping``.\n\n  A pseudo-implementation of this ``to(factory:)``:\n\n  .. code-block:: swift\n\n    public func to\u003cP1\u003e(factory: (P1) -\u003e Element) {\n      // Ask the binder for a provider of P1. This provider\n      // is invalid until the component is constructed\n      // Note that getProvider is an internal method, unlike in Guice.\n      // It also specifies which binding this provider is for to\n      // improve debugging.\n      let dependencyProvider1: Provider\u003cP1\u003e =\n          binder.getProvider(P1.self, requiredFor: Element.self)\n\n      // Create a Provider of Element. This will call the factory\n      // method with the providers\n      let elementProvider: Provider\u003cElement\u003e = Provider {\n          factory(dependencyProvider1.get())\n      }\n\n      // Call the to(provider:) terminating function to finish\n      // this binding\n      to(provider: elementProvider)\n    }\n\n  Since the requesting of the dependent providers happen at configuration time, the object graph is aware of all\n  the bindings and dependencies at configuration time and will fail fast.\n\n\n.. _function type: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Types.html#//apple_ref/doc/uid/TP40014097-CH31-ID449\n\n\nTerminating Methods: ``to\u003cP1, P2, … PN\u003e(factory: (P1, P2, … PN) -\u003e E)`` *(Nth arity)*\n#####################################################################################\n\nWell, we may have more than one requirement to construct a given instance.\nThere aren't `variadic generics`_ in swift. However we used a small script to generate various arities of the\n``to(factory:)`` methods.\n\n.. _variadic generics: https://en.wikipedia.org/wiki/Variadic_template\n\nCollection Bindings\n```````````````````\nIt is sometimes desirable to provide multiple objects of the same type into one collection. A very common use of\nthis would be providing interceptors or filters to an RPC library.\nIn an app, one may want to add to a set of view controllers of a tab bar controller, or settings in a settings page.\n\nThis concept is referred to as *Multibindings*\n`in Dagger \u003chttp://google.github.io/dagger/multibindings.html\u003e`_\nand\n`in Guice \u003chttps://github.com/google/guice/wiki/Multibindings\u003e`_.\n\nProviding to a Set or Dictionary is not an unwanted feature and could probably be built as an extension on top of providing to ``Arrays``.\n\nBinding an element to a collection is very similar to standard `Bind Step`_\\ s,\nbut with the addition of one step: calling ``.intoCollection()`` in the builder definition.::\n\n  binder\n    .bind([Element.self])                // Bind Step\n    .intoCollection()\t// indicates that we are providing an\n                      // element or elements into Array\u003cElement\u003e**\n   [.tagged(with: Tag_For_Element.self)]   // Tag step\n   [.asSingleton()]                        // Scope step\n   {.to(provider:) |                       // Terminating step\n    .to(factory:)  |\n    .to(value:)}\n\nThe `Terminating Step`_ for this builder sequence can either be a factory/value/provider\nof a single ``Element`` or ``Array`` of ``Element``\\ s.\n\n.. _`Property Injection`:\nProperty Injection\n``````````````````\nThere are a few instances where one does not control the construction of an object, but dependency injection would be deemed useful.\nSome of the more common occurrences of this are:\n\n- App Delegate: This is required in every iOS app and is the entry point, but UIKit will construct it.\n- View Controllers constructed via storyboard (in particular via segues): Yes, we all make mistakes. One of those mistakes\n  may have been using Storyboards before they became unwieldy. One does not control the construction of view controllers\n  when using storyboards.\n- XCTestCase: We don't control how they're instantiated, but may want to access objects from an object graph. This is\n  more desirable in higher levels of testing such as UI and integration testing (DI can usually be avoided for lower\n  level unit tests)\n\nCleanse has a solution for this: Property injection (known as Member injection in Guice and Dagger).\n\nIn cleanse, Property injection is a second class citizen by design. Factory/Constructor injection should be used wherever\npossible, but when it won't property injection may be used. Property Injection has a builder language, similar to the\n``BindingBuilder``:\n\n.. code-block:: swift\n\n  binder\n    .bindPropertyInjectionOf(\u003cmetatype of class being injected into\u003e)\n    .to(injector: \u003cproperty injection method\u003e)\n\nThere are two variants of the terminating function, one is where the signature is\n\n.. code-block:: swift\n\n  (Element, P1, P2,  ..., Pn) -\u003e ()\n\nAnd the other is\n\n.. code-block:: swift\n\n  (Element) -\u003e (P1, P2, ..., Pn) -\u003e ()\n\nThe former is to allow for simple injection methods that aren't instance methods, for example:\n\n.. code-block:: swift\n\n  binder\n    .bindPropertyInjectionOf(AClass.self)\n    .to {\n       $0.a = ($1 as TaggedProvider\u003cATag\u003e).get()\n    }\n\nor\n\n.. code-block:: swift\n\n  binder\n    .bindPropertyInjectionOf(BClass.self)\n    .to {\n        $0.injectProperties(superInjector: $1, b: $2, crazyStruct: $3)\n    }\n\nThe latter type of injection method that can be used (``Element -\u003e (P1, P2,  …, Pn) -\u003e ()``) is convenient\nwhen referring to instant methods on the target for injection.\n\nSay we have\n\n.. code-block:: swift\n\n    class FreeBeer {\n      var string1: String!\n      var string2: String!\n\n      func injectProperties(\n        string1: TaggedProvider\u003cString1\u003e,\n        string2: TaggedProvider\u003cString2\u003e\n      ) {\n        self.string1 = string1.get()\n        self.string2 = string2.get()\n      }\n    }\n\nOne can bind a property injection for FreeBeer by doing:\n\n.. code-block:: swift\n\n    binder\n      .bindPropertyInjectionOf(FreeBeer.self)\n      .to(injector: FreeBeer.injectProperties)\n\nThe result type of the expression ``FreeBeer.injectProperties`` is ``FreeBeer -\u003e (TaggedProvider\u003cString1\u003e, TaggedProvider\u003cString2\u003e) -\u003e ()``\n\nAfter binding a property injector for ``Element``, one will be able to request the type ``PropertyInjector\u003cElement\u003e``\nin a factory argument. This has a single method defined as:\n\n.. code-block:: swift\n\n  func injectProperties(into instance: Element)\n\nWhich will then perform property injection into ``Element``.\n\n**Note:** Property injectors in the non-legacy API are unaware of class hierarchies. If one wants property injection to cascade up a class hierarchy, the injector bound may call the inject method for super, or request a ``PropertyInjector\u003cSuperclass\u003e`` as an injector argument and use that.\n\n.. _`Advanced Setup`:\nAdvanced Setup\n``````````````\nWe can make the root of our Cleanse object graph the App Delegate through `Property Injection`_. We must use property injection here because we don't control construction of the app delegate. Now we can model our \"Root\" as an instance of ``PropertyInjector\u003cAppDelegate\u003e`` and then use this object to inject properties into our already constructed App Delegate.\n\nLet's start by redefining the ``RootComponent``:\n\n.. code-block:: swift\n\n    extension AppDelegate {\n      struct Component : Cleanse.RootComponent {\n        // When we call build() it will return the Root type, which is a PropertyInjector\u003cAppDelegate\u003e.\n        // More on how we use the PropertyInjector type later.\n        typealias Root = PropertyInjector\u003cAppDelegate\u003e\n\n        // Required function from Cleanse.RootComponent protocol.\n        static func configureRoot(binder bind: ReceiptBinder\u003cPropertyInjector\u003cAppDelegate\u003e\u003e) -\u003e BindingReceipt\u003cPropertyInjector\u003cAppDelegate\u003e\u003e {\n            return bind.propertyInjector(configuredWith: { bind in\n                bind.to(injector: AppDelegate.injectProperties)\n            })\n        }\n\n        // Required function from Cleanse.RootComponent protocol.\n        static func configure(binder: Binder\u003cUnscoped\u003e) {\n            // Binding go here.\n        }\n      }\n    }\n\nInside of our app delegate, we add the function ``injectProperties``:\n\n.. code-block:: swift\n\n  func injectProperties(_ window: UIWindow) {\n    self.window = window\n  }\n\nNow to wire up our new root object, we can call ``injectProperties(:)`` on ourself in the app delegate:\n\n.. code-block:: swift\n\n  func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -\u003e Bool {\n      // Build our component, and make the property injector\n      let propertyInjector = try! ComponentFactory.of(AppDelegate.Component.self).build(())\n\n       // Now inject the properties into ourselves\n      propertyInjector.injectProperties(into: self)\n\n      window!.makeKeyAndVisible()\n\n      return true\n  }\n\nRunning the app now will yield a new error saying a provider for ``UIWindow`` is missing, but after binding an instance of our ``UIWindow`` and its dependencies, we should be good to go!\n\n.. code-block:: swift\n\n  extension UIWindow {\n    struct Module : Cleanse.Module {\n      public func configure(binder: Binder\u003cSingleton\u003e) {\n        binder\n          .bind(UIWindow.self)\n          // The root app window should only be constructed once.\n          .sharedInScope()\n          .to { (rootViewController: RootViewController) in\n            let window = UIWindow(frame: UIScreen.mainScreen().bounds)\n            window.rootViewController = rootViewController\n            return window\n          }\n      }\n    }\n  }\n\nContributing\n------------\nWe're glad you're interested in Cleanse, and we'd love to see where you take it.\n\nAny contributors to the master Cleanse repository must sign the `Individual Contributor License Agreement (CLA)`_. It's\na short form that covers our bases and makes sure you're eligible to contribute.\n\n.. _Individual Contributor License Agreement (CLA): https://spreadsheets.google.com/spreadsheet/viewform?formkey=dDViT2xzUHAwRkI3X3k5Z0lQM091OGc6MQ\u0026ndplr=1\n\n\nLicense\n-------\n`Apache 2.0`_\n\n.. _Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0.html\n.. _associated type: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Generics.html#//apple_ref/doc/uid/TP40014097-CH26-ID189\n.. _associatedtype: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Generics.html#//apple_ref/doc/uid/TP40014097-CH26-ID189\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsquare%2Fcleanse","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsquare%2Fcleanse","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsquare%2Fcleanse/lists"}