Tranquillity is a lightweight but powerful dependency injection library for swift.




Tranquillity is a lightweight but powerful dependency injection library for swift.

The name "Tranquillity" laid the foundation in the basic principles of library: clarity, simplicity and security.

It says - use the library and you will be calm for your dependencies.

Language switch: English, Russian

About Dependendy Injection

Dependency Injections is a software design pattern in which someone delivers dependencies to an object.

Is one form of the broader technique of Inversion Of Control and help the Dependency Inversion Principle

For more details you can read this link

Also I recommend you to read Glossary which will help to better understand the terms.




Graph API


The library supports three popular package managers: Cocoapods, Carthage, SwiftPM.


Add the following lines to your Podfile:

pod 'DITranquillity'


You can use "Xcode/File/Swift Packages/Add Package Dependency..." and write github url:

Also you can edit your Package.swift and the following line into section dependencies:

.package(url: "", from: "3.8.4")

And don't forget to specify in your section target wrote dependency line:

.product(name: "DITranquillity")

Attention! - SwiftPM unsupport features from the "UI" section.


Add the following lines to your Cartfile:

github "ivlevAstef/DITranquillity"

Carthage support "UI" and "GraphAPI" section no additional actions.


The library uses a declarative style of dependency description, and allows you to separate your application code from dependency description code.

For a quick entry, let's look at an example code of one simplified VIPER screen:

) -> Void) } class AuthInteractorImpl: AuthInteractor { func login(name: String, password: String, completion: (Result) -> Void) { ... } } ">
/// Dependency description

let container = DIContainer()



  .injection(cycle: true, \.presenter)


/// Application start point

let router: LoginRouter = container.resolve()
window.rootViewController = router.rootViewController

/// Application Code

import SwiftLazy

class LoginRouter {
    let rootViewController = UINavigationController()
    private let loginPresenterProvider: Provider
    init(loginPresenterProvider: Provider) {
        loginPresenterProvider = loginPresenterProvider
    func start() {
        let presenter = loginPresenterProvider.value
        presenter.loginSuccessCallback = { [weak self] _ in
        // Your can write code without force cast, it's code simple example
        rootViewController.push(presenter.view as! UIViewController)

protocol LoginPresenter: class {
    var loginSuccessCallback: ((_ userId: String) -> Void)?
    func login(name: String, password: String)

protocol LoginView: class {
    func showError(text: String)

class LoginPresenterImpl: LoginPresenter {
    private weak var view: LoginView?
    private let authInteractor: AuthInteractor
    init(view: LoginView, authInteractor: AuthInteractor) {
        self.view = view
        self.authInteractor = authInteractor
    func login(name: String, password: String) {
        if name.isEmpty || password.isEmpty {
            view?.showError(text: "fill input")
        authInteractor.login(name: name, password: password, completion: { [weak self] result in
            switch result {
            case .failure(let error): 
                self?.view?.showError(text: "\(error)")
            case .success(let userId):

class LoginViewController: UIViewController, LoginView {
    var presenter: LoginPresenter!
    func showError(text: String) {
        showAlert(title: "Error", message: text)
    private func tapOnLoginButton() {
        presenter.login(name: nameTextField.text ?? "", password: passwordTextField.text ?? "")

protocol AuthInteractor: class {
    func login(name: String, password: String, completion: (Result<String, Error>) -> Void)

class AuthInteractorImpl: AuthInteractor {
    func login(name: String, password: String, completion: (Result<String, Error>) -> Void) {

As you can see, the dependency description code takes a small part, and the application code doen't know about how dependencies are implemented.

Also your can show samples:

Also your can read articles:


iOS 9.0+,macOS 10.10+,tvOS 9.0+, watchOS, linux; ARC

  • Swift 5.0-5.3: Xcode 10.2-12.3; version >= 3.6.3
  • Swift 4.2: Xcode 10; version >= 3.4.3
  • Swift 4.1: Xcode 9.3; version >= 3.2.3
  • Swift 4.0: Xcode 9.0; version >= 3.0.5
  • Swift 3.0-3.2: Xcode 8.0-9.0; 0.9.5 <= version < 3.7.0
  • Swift 2.3: Xcode 7.0; version < 0.9.5


See CHANGELOG file or releases.

History and Plans

  • v1.x.x - Started
  • v2.x.x - Stabilization
  • v3.x.x - Evolution and Features
  • v4.x.x - Graph API and Optimization. Also Documentation and Marketing
  • v5.x.x - Pre compile time validation


I've found a bug, or have a feature request

Please raise a GitHub issue.

I've found a defect in documentation, or thought up how to improve it

Please help library development and create pull requests


If you like my library, then support the library by putting star.

You can also support the author of the library with a donation:



You can feel free to ask the question at e-mail: [email protected].

  • resolve many on lazy

    resolve many on lazy

    Hi, let test: [Lazy<Provider>] = [*container] is work but let test: [Lazy<Provider>] = many(*container) doesn't

    Fatal error: Can't cast Optional to Array<Lazy>

    what workaround could be? thanx

    opened by evgeniy-bizhanov 8
  • Custom scopes

    Custom scopes


    Thank you for the library! It's nice to have a decent DI-library for pure Swift projects.

    Could you please clarify a couple of things for me. I'm trying to wrap my head around custom scope objects. Let's say I have three VCs: VC1 -> VC2 -> VC3. And I want to share some object between them.

    I understand, that I can just register the object as single (.single, .lazySingle or .weakSingle). But it will live so long as the whole app. In my case I want to bind its lifecycle to the aforementioned view controllers.

    What is the best way to achieve this? Should I create another DIContainer just for these VCs?

    opened by stanmots 7
  • DIExtension (arguments) unsupoort multithread

    DIExtension (arguments) unsupoort multithread

    Now if I resolve one object with arguments from more threads app can crash - because set arguments and resolve not atomic operation:

    container.extensions(for: YourType.self)?.setArgs(arg1)
    container.resolve() as YourType

    This problems actual for Provide1, Provide2... and Lazy1, Lazy2 because he using argument.

    setArgs - устанавливает аргументы к указанному типу, но если это сделать из многих потоков, то аргументы будут в итоге от последнего.

    первый resolve() же получит объект с аргументами от последнего, а последующие упадут.

    Как решать - видимо надо сделать resolve который принимает argument-ы всеже. Да аргументы по типу, но это не отдельным расширением. В общем DIExtension походу надо удалять.

    opened by ivlevAstef 6
  • Падает на @State в SwiftUI

    Падает на @State в SwiftUI

    Добрый день!

    Я добавляю в свою библиотеку поддержку SwiftUI, для DI использую DITranquality. @ObservedObject работает, а при добавлении @State падает с ошибкой проверки графа error: Invalid reference from <Component. type: TestView; path: TestView.swift:67> because not found component for type: Int Fatal error: invalid graph: file Не пойму в чем дело.

    opened by kocherovets 4
  • Weak parent

    Weak parent

    Hi. In my current architecture, I'm using coordinators with injected containers. (I didn't found method collaborate so I decide to use init(: parent)) Code:

    protocol Coordinator: class {
        var parent: Coordinator? { get set }
        var childCoordinators: [Coordinator] { get set }
        var navigationController: UINavigationController { get }
        var container: DIContainer { get set }
        func start()
    extension Coordinator {
        func store(coordinator: Coordinator) {
            coordinator.parent = self
            coordinator.container = DIContainer(parent: container)

    Today I've checked memory graph and spotted multiple leaks in coordinators. The reason was that your container holding a strong reference on the parent. I've fixed the problem by making container DIContainer! and explicitly assign him nil. Code:

    func free(coordinator: Coordinator) {
            coordinator.container = nil
            childCoordinators.removeAll(where: { $0 === coordinator })

    But in my opinion, the best solution will be adding weak to parent. Or at least make parent public property. What do you think on this? Maybe I'm using container in the wrong way. Thanks.

    opened by sssbohdan 4
  • Liibrary crashes when trying to instantinate view controller

    Liibrary crashes when trying to instantinate view controller

    Hello! App library crashes when I'm trying to instantiate view controller from container

    Here is a component:

    class AppComponent: DIComponent{
        var scope: DIComponentScope { return .public }
        func load(builder: DIContainerBuilder){
            builder.register(type: UIStoryboard.self)
                .set(name: "Main")
                .initial { DIStoryboard(name: "Main", bundle: nil, container: $0) }
            builder.register(vc: StartupVC.self)
                .initial(useStoryboard: {container in try container.resolve(name: "Main")}, identifier: "startup")


        func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
            let builder = DIContainerBuilder()
            builder.register(component: AppComponent())
            let container = try!
            let viewController = try! container.resolve(StartupVC.self)
            self.window = UIWindow(frame: UIScreen.main.bounds)
            self.window?.rootViewController = viewController
            return true

    Crash is on this line let viewController = try! container.resolve(StartupVC.self)

    fatal error: 'try!' expression unexpectedly raised an error: Cannot found initial method with signature: (DIContainer) throws -> Any. Use: Register type: StartupVC in file: AppComponent.swift on line: 23

    Is it a bug or am I doing something wrong? I can send you sample project.

    opened by vchmezov 4
  • Внедрение зависимостей через свойства используя KeyPath swift 5

    Внедрение зависимостей через свойства используя KeyPath swift 5

    Спасибо за библиотеку! в swift 5 не поддерживается внедрение зависимостей через свойства используя KeyPath если свойство private(set)

    class AppPart: DIPart {
        static func load(container: DIContainer) {
    class Presenter {
    class ViewController {
        private(set) var presenter: Presenter!
    opened by makleso6 3
  • New registration tagging proposal

    New registration tagging proposal

    Proposal. Problem: Current implementation of “tags” in library based on objects types (or strings, but its not compile-safe). It is not possible now to use polymorphism like:

    class A {}
    class B:A {}
    let tag: A.Type = B.self
        .as(MyClass.self, tag: B.self)
    let myOBJ: MyClass? = c.resolve(tag)

    Resolver will produce nil in myOBJ resolving, cause container will be used compile-time type of tag (A.Type), not actual type stored in tag variable.

    And now we hame “name” feature that can be used similar way as tags, but string not compile-safe and it is easy to make typo mistake during development. Because both “name” and “tag” exists in library, one of them looks like a hack, that exists for solving problem of opposite implementation.

    Proposal: For easier and more intuitive usage of marking registrations I suggest implement Notification.Name-like implementation or Enum implementation.


    struct DITag {
        enum Scope<T> {
            case public
            case restricted(T.Type)
        private let value: String
        private let tagScopeID: ObjectIdentifier
        Init<T>(value: String, scope: Scope<T> = .public)
    struct MyModule {}
    extension DITag { 
        static let myTag = DITag(value: “simpleTag”)
        static let myModuleTag = DITag(value: “simpleTag2”, scope: .restricted(MuModule.self))
       .as(MyClass.self, tag: .myTag)
       .as(MyClass.self, tag: .myModuleTag)
    let obj = container.resolve(tag: .myTag)


    protocol DITag {
        var stringValue: String { get }
    enum MyTags: String, DITag {
       case tag1
       case tag2
        .as(MyClass.self, tag: MyTags.tag1)
    let obj = container.resolve(tag: MyTags.tag1)


    1. Less confusing cause we have only one tagged implementations (we have String tags and Typed tags now)
    2. More intuitive registration and resolving (enum-case like)
    3. Can be polymorphed
    4. Typo mistakes still can be avoided as in current Typed tags implementation

    Difference between two variants: In variant 1 anyone from another frameworks can get access to your tagged variable without actually having access to internal tag if you declare DITag.Scope as public just by passing same string value in DITag initialisation. In variant 2, you have no possibility to share access to tag, because of capturing enum’s type in “as(_:tag:)” registration. Enum’s type capturing is mandatory cause of enum’s case string values overlapping.

    opened by Nekitosss 3
  • Lazy Provide

    Lazy Provide

    Add small library with lazy and provide functionality.

    Integrate DITranquillity with this library. Add public protocol, for can use other library:

    protocol InstanceWrapper {
      static var wrappedType: Any.Type { get }
      init?(container: DIContainer, resolver: () -> (Any?))
    opened by ivlevAstef 3
  • Change register syntax

    Change register syntax


    register(Type.self, Protocol.self,...) .initial { return Obj(inject: $0) }

    first string contains all type names and after wrote function for create object.

    as - removed

    question task 
    opened by ivlevAstef 3
  • supported parent

    supported parent

    let modificator = Modificator() .asType(Logger.self) .instanceSingle()

    builder.register{ ConsoleLogger() } .use(modificator: modificator)

    builder.register{ FileLogger(file: "file.log") } .use(modificator: modificator)

    builder.register{ ServerLogger(server: "") } .use(modificator: modificator)

    builder.register{ MainLogger(loggers: **!$0) } .use(modificator: modificator) .asDefault()

    opened by ivlevAstef 3
  • Множественные одинаковые register

    Множественные одинаковые register

    При наличии нескольких одинаковых register resolve падает с критической ошибкой:

    protocol P {
    class C: P {
    container.register(C.init).as(P.self).lifetime(.single) // 1
    container.register(C.init).as(P.self).lifetime(.single) // 2
    let obj: C = container.resolve() // crash

    Ситуация довольно типовая, когда выражения 1 и 2 находятся в разных модулях. lifetime ситуацию не меняет.

    opened by VasilyKrainov 2
  • Refactory resolve system

    Refactory resolve system

    Current resolve system make without delay Maker - Lazy, Provider. It lead to not fully support Delay Maker with other modifications - many, tags.

    Also current system can faster, and simplify

    opened by ivlevAstef 1
  • Integrated with SourceKittenFramework

    Integrated with SourceKittenFramework

    Library can get AST, can wrote warnings/errors dyring build.

    But it's hard...

    opened by ivlevAstef 2
  • contains


    Added contains function in DITranquillity:

    container.contains(type: Protocol.self) // contains(type: "Protocol") container.contains(component: Component.self) // contains(component: "Component") container.contains(module: Module.self) // contains(module: "Module")

    opened by ivlevAstef 2
  • Extensions


    Extensions - add additional capabilities, in runtime. Needs for other libraries

    class VC: UIViewController {
      var presenter: Presenter!
    // where get arg1?
    class Presenter {
      let server: Server!
      let arg1: Int
      init(server: server, arg1: Int) {
        self.server = server
        self.arg1 = arg1
    showVC() {
      let runtimeArg1 = 125
      let runtimeArg2 = 125
      // extension variable need for retain Extension
      let extension = DIExtensions.resolve(filter: Presenter.self) { container in
        return Presenter(server: try! *container, arg1: runtimeArg1)
      } // if somebody resolve Presenter, then call extension
      // or
      let extension = DIExtensions.initial(filter: Presenter.self) { container in
        return Presenter(server: try! *container, arg1: runtimeArg1)
      } // if from somewhere get Presenter, then call extension
      let extension = DIExtensions.postInit(filter: Presenter.self) { container, presenter in
        presenter.arg2 = runtimeArg2
      } // if Presenter full create, then call extension
      let vc =
    opened by ivlevAstef 2
  • v4.3.4(Sep 25, 2021)

    Add simple one modificator injection into initialize method. For example: Old: container.register { Cat(name: arg($0), owner: $1, home: $2) } New: container.register(Cat.init) { arg($0) }

    Source code(tar.gz)
    Source code(zip)
  • v4.3.3(Jun 23, 2021)

    Fix argument injection for Tag and named resolve. for example:

    container.register { MyClass(inj: arg($0)) }
        .as(name: "Name", MyProtocol.self)
        .as(tag: MyTag.self, MyProtocol.self)
    let arg = AnyArgument(type: MyProtocol.self, value: 1)
    let obj1: MyProtocol = container.resolve(name: "Name", arguments: arg)
    let obj2: MyProtocol = by(tag: MyTag.self, on: container.resolve(arguments: arg))
    Source code(tar.gz)
    Source code(zip)
  • v4.3.2(Jun 15, 2021)

    Fix arguments resolve if for resolve used none base type. for example: let a: T? = container.resolve(args: ...). In current example T is Optional. Also fix if T use many or tag.

    Source code(tar.gz)
    Source code(zip)
  • v4.3.0(Jun 9, 2021)

    Warning! This version change public API!

    • Update arguments. Now inject arguments it's thread save operation. Also change syntax - remove extensions, and now inject arguments use resolve method in container. see

    Source code(tar.gz)
    Source code(zip)
  • v4.2.3(Apr 28, 2021)

  • v4.2.2(Apr 27, 2021)

    • Improve thread safe for public scopes DICacheStorage. Actually only if you use custom lifetime.
    • Fix thread safe for methods initializeSingletonObjects and initializeObjectsForScope
    Source code(tar.gz)
    Source code(zip)
  • v4.2.1(Apr 6, 2021)

  • v4.2.0(Mar 14, 2021)

    Add new settings - enable disable multithread support. Default enable. Improve resolve speed - fix small performance bug. Increase speed on x6-7

    Source code(tar.gz)
    Source code(zip)
  • v4.1.7(Nov 30, 2020)

  • v4.1.5(Nov 17, 2020)

    • Small fix log bugs - if your use many in logs can shown incorrect warning.
    • Add new feature: initialize objects for scope. This feature equals to initializeSingletonObjects but for your custom lifetime/scope.
    Source code(tar.gz)
    Source code(zip)
  • v4.1.4(Oct 23, 2020)

    Fix library bug - potencial memory leaks. This bug manifested if your use Provider/Lazy and call get object until initialize other dependency (for example inside init method).

    Source code(tar.gz)
    Source code(zip)
  • v4.1.1(Sep 5, 2020)

    • Add test - it's a more powerful analog default needed for tests.
    • Small improve Graph API - fix access scope and fix getted type for unknown and arg.
    Source code(tar.gz)
    Source code(zip)
  • v4.1.0(Jul 7, 2020)

    • Add Graph API - now your get dependency graph.
    • Change graph validation - change syntax, add validation cases, improve validation cycles speed x1000-10000
    • Fix small bugs and full synchronise validation graph and real usage.
    Source code(tar.gz)
    Source code(zip)
  • v4.0.0(Jul 1, 2020)

  • v3.9.3(Dec 18, 2019)

  • v3.9.1(Nov 30, 2019)

  • v3.9.0(Oct 11, 2019)

    DANGER! Changed logic for Provider and Lazy - now objectGraph object not retained until use Provider and Lazy. It's remove potencial memory leak, but can changed your program logic - if your not retained objects, this objects can removed, and remake after make object by Provider or Lazy.

    Source code(tar.gz)
    Source code(zip)
  • v3.8.4(Sep 28, 2019)

  • v3.8.3(Sep 26, 2019)

  • v3.8.2(Sep 17, 2019)

    Support Lazy with tags, many and other combinations. for example: let services: [Lazy<ServiceProtocol>] = many(by(tag: FooService.self, on: *container))

    Source code(tar.gz)
    Source code(zip)
  • v3.8.1(Sep 10, 2019)

  • v3.8.0(Sep 5, 2019)

    • Remove bundle from DIFramework - now used only DIFramework. It's need for support module architecture on static libraries.
    • Small improve logs - add make log.
    Source code(tar.gz)
    Source code(zip)
  • v3.7.4(Sep 5, 2019)

  • v3.7.2(Jul 19, 2019)

  • v3.7.1(May 22, 2019)

    • Fully support optional register. c.register { optionalValue } now can correct resolve.
    • Improve logs for optional register if optional is nil.
    Source code(tar.gz)
    Source code(zip)
  • v3.7.0(May 11, 2019)

  • v3.6.4(May 1, 2019)

Ivlev Alexander
Senior iOS/Game developer on Swift/C++
Ivlev Alexander
Typhoon Powerful dependency injection for Cocoa and CocoaTouch.

Typhoon Powerful dependency injection for Cocoa and CocoaTouch. Lightweight, yet full-featured and super-easy to use. Pilgrim is a pure Swift successo 2.7k Dec 14, 2022
Swinject is a lightweight dependency injection framework for Swift.

Swinject Swinject is a lightweight dependency injection framework for Swift. Dependency injection (DI) is a software design pattern that implements In

null 5.6k Dec 31, 2022
Container is a lightweight dependency injection framework for Swift.

Container Container is a lightweight dependency injection framework for Swift. Installation is available in the Swift Package Manager. Swift Package M

Aleksei Artemev 17 Oct 13, 2022
Toledo - a dependency injection library for Swift that statically generates resolvers at compile-time.

Toledo Toledo is a dependency injection library for Swift that statically generates resolvers at compile-time. Index Features Installation Usage Licen

Valentin Radu 18 Nov 25, 2022
DIContainer Swift is an ultra-light dependency injection container made to help developers to handle dependencies easily. It works with Swift 5.1 or above.

?? DIContainer Swift It is an ultra-light dependency injection container made to help developers to handle dependencies easily. We know that handle wi

Victor Carvalho Tavernari 10 Nov 23, 2022
Pilgrim - Dependency injection for Swift (iOS, OSX, Linux). Strongly typed, pure Swift successor to Typhoon. Pilgrim is a dependency injection library for Swift with the following features: Minimal runtime-only library that works with pure Swift (s 60 Oct 24, 2022
Injector - A Swift package for simple dependency injection that also supports Swift UI previews

A Swift package for simple dependency injection that also supports Swift UI prev

null 6 Aug 9, 2022
Cleanse is a dependency injection framework for Swift.

Cleanse - Swift Dependency Injection Cleanse is a dependency injection framework for Swift. It is designed from the ground-up with developer experienc

Square 1.7k Dec 16, 2022
DIKit Dependency Injection Framework for Swift, inspired by KOIN.

DIKit Dependency Injection Framework for Swift, inspired by KOIN. Basically an implementation of service-locator pattern, living within the applicatio

null 95 Dec 22, 2022
Dependency Injection framework for Swift (iOS/macOS/Linux)

Declarative, easy-to-use and safe Dependency Injection framework for Swift (iOS/macOS/Linux) Features Dependency declaration via property wrappers or

Scribd 684 Dec 12, 2022
Swift Ultralight Dependency Injection / Service Locator framework

Swift Ultralight Dependency Injection / Service Locator framework

Michael Long 1.9k Jan 6, 2023
Kraken - Simple Dependency Injection container for Swift. Use protocols to resolve dependencies with easy-to-use syntax!

Kraken Photo courtesy of Introduction Kraken is a simple Dependency Injection Container. It's aimed to be as simple as

Syed Sabir Salman-Al-Musawi 1 Oct 9, 2020
ViperServices - Simple dependency injection container for services written for iOS in swift supporting boot order

ViperServices Introduction ViperServices is dependency injection container for iOS applications written in Swift. It is more lightweight and simple in

Siarhei Ladzeika 5 Dec 8, 2022
Needle - Compile-time safe Swift dependency injection framework

Needle is a dependency injection (DI) system for Swift. Unlike other DI frameworks, such as Cleanse, Swinject, Needle encourages hierarchical DI struc

Uber Open Source 1.4k Jan 3, 2023
CarbonGraph - A Swift dependency injection / lookup framework for iOS

CarbonGraph is a Swift dependency injection / lookup framework for iOS. You can

Baidu 244 Jan 4, 2023
A new approach to Container-Based Dependency Injection for Swift and SwiftUI.

A new approach to Container-Based Dependency Injection for Swift and SwiftUI. Why do something new? Resolver was my first Dependency Injection system.

Michael Long 573 Jan 2, 2023
Effortless modular dependency injection for Swift.

Inject Effortless modular dependency injection for Swift. Sometimes during the app development process we need to replace instances of classes or acto

Maxim Bazarov 40 Dec 6, 2022
Corridor A Coreader-like Dependency Injection μFramework

Corridor A Coreader-like Dependency Injection μFramework Table of Contents Why | Examples | Usage | Installation | Credits & License | Why In order to

symentis GmbH 60 Nov 1, 2022
Deli is an easy-to-use Dependency Injection Container that creates DI containers

Deli is an easy-to-use Dependency Injection Container that creates DI containers with all required registrations and corresponding factories.

Jungwon An 134 Aug 10, 2022