- Notifications
You must be signed in to change notification settings - Fork545
Dependency injection framework for Swift with iOS/macOS/Linux
License
Swinject/Swinject
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
Swinject is a lightweightdependency injection framework for Swift.
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.
Swinject is maintained by theFaire Wholesale Inc. mobile platform team.
- Pure Swift Type Support
- Injection with Arguments
- Initializer/Property/Method Injections
- Initialization Callback
- Circular Dependency Injection
- Object Scopes as None (Transient), Graph, Container (Singleton) and Hierarchy
- Support of both Reference andValue Types
- Self-registration (Self-binding)
- Container Hierarchy
- Thread Safety
- Modular Components
- SwinjectPropertyLoader: Loading property values from resources.
- SwinjectStoryboard: Automatic dependency injection via Storyboard.
- Swinject-CodeGen: Type-safe code generation of
Containerfrom a CSV/YAML file defining dependencies. - SwinjectAutoregistration: Automatic registration of services by leveraging the Swift Generics.
- iOS 11.0+ / Mac OS X 10.13+ / watchOS 4.0+ / tvOS 11.0+
- Xcode 14.3+
- Swift 4.2+
- Carthage 0.18+ (if you use)
- CocoaPods 1.1.1+ (if you use)
Swinject is available throughCarthage,CocoaPods, orSwift Package Manager.
To install Swinject with Carthage, add the following line to yourCartfile.
github "Swinject/Swinject"# Uncomment if you use SwinjectStoryboard# github "Swinject/SwinjectStoryboard"Then runcarthage update --no-use-binaries command or justcarthage update. For details of the installation and usage of Carthage, visitits project page.
To install Swinject with CocoaPods, add the following lines to yourPodfile.
source'https://github.com/CocoaPods/Specs.git'platform:ios,'11.0'# or platform :osx, '10.13' if your target is OS X.use_frameworks!pod'Swinject'# Uncomment if you use SwinjectStoryboard# pod 'SwinjectStoryboard'
Then runpod install command. For details of the installation and usage of CocoaPods, visitits official website.
inPackage.swift add the following:
dependencies:[ // Dependencies declare other packages that this package depends on. // .package(url: /* package url */, from: "1.0.0"),.package(url:"https://github.com/Swinject/Swinject.git", from:"2.8.0")],targets:[.target( name:"MyProject", dependencies:[...,"Swinject"])...]
- Technical documents including patterns of dependency injection and examples.
- API reference
First, register a service and component pair to aContainer, where the component is created by the registered closure as a factory. In this example,Cat andPetOwner are component classes implementingAnimal andPerson service protocols, respectively.
letcontainer=Container()container.register(Animal.self){ _inCat(name:"Mimi")}container.register(Person.self){ rinPetOwner(pet: r.resolve(Animal.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!
letperson= container.resolve(Person.self)!person.play() // prints "I'm playing with Mimi."
Where definitions of the protocols and classes are
protocolAnimal{varname:String?{get}}classCat:Animal{letname:String?init(name:String?){self.name= name}}
and
protocolPerson{func play()}classPetOwner:Person{letpet:Animalinit(pet:Animal){self.pet= pet}func play(){letname= pet.name??"someone"print("I'm playing with\(name).")}}
Notice that thepet ofPetOwner is automatically set as the instance ofCat whenPerson is resolved to the instance ofPetOwner. 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.
Services must be registered to a container before they are used. The typical registration approach will differ depending upon whether you are usingSwinjectStoryboard or not.
The following view controller class is used in addition to the protocols and classes above in the examples below.
classPersonViewController:UIViewController{varperson:Person?}
Import SwinjectStoryboard at the top of your swift source file.
import SwinjectStoryboardServices should be registered in an extension ofSwinjectStoryboard if you useSwinjectStoryboard. Refer tothe project page of SwinjectStoryboard for further details.
extensionSwinjectStoryboard{@objcclassfunc setup(){ defaultContainer.register(Animal.self){ _inCat(name:"Mimi")} defaultContainer.register(Person.self){ rinPetOwner(pet: r.resolve(Animal.self)!)} defaultContainer.register(PersonViewController.self){ rinletcontroller=PersonViewController() controller.person= r.resolve(Person.self)return controller}}}
If you do not useSwinjectStoryboard to instantiate view controllers, services should be registered to a container in your application'sAppDelegate. Registering before exitingapplication:didFinishLaunchingWithOptions: will ensure that the services are setup appropriately before they are used.
classAppDelegate:UIResponder,UIApplicationDelegate{varwindow:UIWindow?letcontainer:Container={letcontainer=Container() container.register(Animal.self){ _inCat(name:"Mimi")} container.register(Person.self){ rinPetOwner(pet: r.resolve(Animal.self)!)} container.register(PersonViewController.self){ rinletcontroller=PersonViewController() controller.person= r.resolve(Person.self)return controller}return container}()func application( _ application:UIApplication, didFinishLaunchingWithOptions launchOptions:[UIApplicationLaunchOptionsKey:Any]?=nil)->Bool{ // Instantiate a window.letwindow=UIWindow(frame:UIScreen.main.bounds) window.makeKeyAndVisible()self.window= window // Instantiate the root view controller with dependencies injected by the container. window.rootViewController= container.resolve(PersonViewController.self)returntrue}}
Notice that the example uses a convenience initializer taking a closure to register services to the new instance ofContainer.
The project containsSample-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 selectEditor > Execute Playground menu in Xcode.
Some example apps using Swinject can be found onGitHub.
The following blog posts introduce the concept of dependency injection and Swinject.
- Dependency Injection Tutorial for iOS: Getting StartedbyIrina Galata
- Swinject Tutorial for iOS: Getting StartedbyGemma Barlow
- iOS Dependency Injection Using SwinjectbyAli Akhtar
- DI in iOS: Complete guidebyVitaly Batrakov
Thanks the authors!
A guide tosubmit issues, to ask general questions, or toopen pull requests ishere.
- Stack Overflow we are trying to monitor questions tagged
swinject
The DI container features of Swinject are inspired by:
and highly inspired by:
MIT license. See theLICENSE file for details.
About
Dependency injection framework for Swift with iOS/macOS/Linux
Topics
Resources
License
Contributing
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
Uh oh!
There was an error while loading.Please reload this page.