Skip to content

Repository files navigation

DIKit

Build Status

A statically typed dependency injector for Swift.

Overview

DIKit provides interfaces to express dependency graph. A code generator named dikitgen finds implementations of the interfaces, and generate codes which satisfies dependency graph.

The main parts of DIKit are injectable types and provider methods, and both of them are to declare dependencies of types.

Injectable types are types that conform to Injectable protocol.

publicprotocolInjectable{associatedtypeDependencyinit(dependency:Dependency)}

A conformer of Injectable protocol must have associated type Dependency as a struct. You declare dependencies of the Injectable conformer as stored properties of Dependency type. For example, suppose we have ProfileViewController class, and its dependencies are User, APIClient and Database. Following example code illustrates how to declare dependencies by conforming Injectable protocol.

finalclassProfileViewController:Injectable{structDependency{letuser:UserletapiClient:APIClientletdatabase:Database}init(dependency:Dependency){...}}

Provider methods are methods of inheritor of Resolver protocol, which is a marker protocol for code generation.

publicprotocolResolver{}

Provider methods declares that which non-injectable types can be instantiated automatically. In the example above, APIClient and Database are non-injectable type, but they can be provided in the same ways in most cases. In this situation, define provider methods for the types in an inheritor of Resolver protocol, so that instances of the types are provided automatically.

protocolAppResolver:Resolver{func provideAPIClient()->APIClientfunc provideDatabase()->Database}

In short, we have following situation so far:

  • Dependencies of ProfileViewController are User, APIClient and Database.
  • Instances of APIClient and Database are provided automatically.
  • An instance of User must be provided manually to instantiate ProfileViewController.

dikitgen generates following code for the declarations:

extensionAppResolver{func resolveAPIClient()->APIClient{returnprovideAPIClient()}func resolveDatabase()->Database{returnprovideDatabase()}func resolveViewController(user:User)->ProfileViewController{letapiClient=resolveAPIClient()letdatabase=resolveDatabase()returnProfileViewController(dependency:.init(user: User, apiClient: apiClient, database: Database))}}

To use generated code, you have to implement a concrete type of AppResolver.

finalclassAppResolverImpl:AppResolver{letapiClient:APIClient=...letdatabase:Database=...func provideAPIClient(){return apiClient
}func provideDatabase(){return database
}}

Since AppResolver is a protocol, all implementations of provider methods are checked at compile time. If you would like to create mock version of AppResolver for unit testing, define another concrete type of AppResolver. It can be used the same as AppResolverImpl.

Now, you can instantiate ProfileViewController like below:

letappResolver=AppResolverImpl()letuser:User=...letviewController= appResolver.resolveViewController(user: user)

Requirements

  • Code generator: Swift 4.1+ / Xcode 9.4+
  • Runtime library: macOS 10.11+ / iOS 9.0+ / watchOS 2.0+ / tvOS 9.0+

Installation

Install code generator dikitgen first.

mint install ishkawa/DIKit dikitgen

From Source

git clone https://github.com/ishkawa/DIKit.git
cd DIKit
make install

Then, integrate DIKit.framework to your project. There are some option to install DIKit.framework.

  • Manual: Clone this repository and add DIKit.xcodeproj to your project.
  • Carthage: Add a line github "ishkawa/DIKIt" to your Cartfile and run carthage update.

Optionally, insert shell script running dikitgen to early part of build phases.

if which dikitgen >/dev/null;then
dikitgen ${SRCROOT}/YOUR_PROJECT >${SRCROOT}/YOUR_PROJECT/AppResolver.generated.swift
elseecho"warning: dikitgen not installed, download from https://github.com/ishkawa/DIKit"fi

About

A statically typed dependency injector for Swift.

Resources

Stars

301 stars

Watchers

9 watching

Forks

Releases

Packages

Used by

Contributors

Languages