Swinject is a lightweight dependency injection framework for Swift, inspired by Ninject, Autofac, Typhoon, and highly inspired by Funq.
Dependency injection (DI) is a software design pattern that implements Inversion of Control (IoC) for resolving dependencies. In the pattern, Swinject helps your app split into loosely-coupled components, which can be developed, tested and maintained more easily. Swinject is powered by the Swift generic type system and first class functions to define dependencies of your app simply and fluently.
- Pure Swift Type Injection
- Initializer/Property/Method Injections
- Initialization Callback
- Circular Dependency Injection
- Injection with Arguments
- Self-registration (Self-binding)
- Container Hierarchy
- Object Scopes as None (Transient), Graph, Container (Singleton) and Hierarchy
- Injection of both Reference and Value Types
- Storyboard
- iOS 8.0+ / Mac OS X 10.10+ / watchOS 2
- Xcode 7.0
Swinject is available through Carthage or CocoaPods.
To install Swinject with Carthage, add the following line to your Cartfile
.
github "Swinject/Swinject" ~> 0.2
Then run carthage update --no-use-binaries
command or just carthage update
. For details of the installation and usage of Carthage, visit its project page.
To install Swinject with CocoaPods, add the following lines to your Podfile
.
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
use_frameworks!
pod 'Swinject', '~> 0.2'
Then run pod install
command. For details of the installation and usage of CocoaPods, visit its official website.
All documentation can be found in the Documentation folder, including patterns of dependency injection and examples.
First, register a service and component pair to a Container
, where the component is created by the registered closure as a factory. In this example, Cat
and PetOwner
are component classes implementing AnimalType
and PersonType
service protocols, respectively.
let container = Container()
container.register(AnimalType.self) { _ in Cat(name: "Mimi") }
container.register(PersonType.self) { r in
PetOwner(pet: r.resolve(AnimalType.self)!)
}
Then get an instance of a service from the container. The person is resolved to a pet owner, and playing with the cat named Mimi!
let person = container.resolve(PersonType.self)!
person.play() // prints "I'm playing with Mimi."
Where definitions of the protocols and classes are
protocol AnimalType {
var name: String? { get }
}
class Cat: AnimalType {
let name: String?
init(name: String?) {
self.name = name
}
}
and
protocol PersonType {
func play()
}
class PetOwner: PersonType {
let pet: AnimalType
init(pet: AnimalType) {
self.pet = pet
}
func play() {
let name = pet.name ?? "someone"
print("I'm playing with \(name).")
}
}
Notice that the pet
of PetOwner
is automatically set as the instance of Cat
when PersonType
is resolved to the instance of PetOwner
. If a container already set up is given, you do not have to care what are the actual types of the services and how they are created with their dependency.
The project contains Sample-iOS.playground
to demonstrate the features of Swinject. Download or clone the project, run the playground, modify it, and play with it to learn Swinject.
To run the playground in the project, first build the project, then select Editor > Execute Playground
menu in Xcode.
- SwinjectSimpleExample demonstrates dependency injection and Swinject in a simple weather app that lists current weather information at some locations.
- SwinjectMVVMExample demonstrates dependency injection with Swift and reactive programming with ReactiveCocoa in MVVM architecture.
The following blog posts introduce Swinject and the concept of dependency injection.
- Dependency Injection Framework for Swift - Introduction to Swinject
- Dependency Injection Framework for Swift - Simple Weather App Example with Swinject Part 1/2
- Dependency Injection Framework for Swift - Simple Weather App Example with Swinject Part 2/2
MIT license. See the LICENSE file for details.