Light IoC container for Swift.
LightIoC is an easy-to-use Dependency Injection (DI) framework for Swift, implementing automatic dependency injection. It manages object creation and it's life-time, and also injects dependencies to the class. The IoC container creates an object of the specified class and also injects all the dependency objects through properties at run time. This is done so that you don't have to create and manage objects manually.
DI guides you to make SOLID applications.
- Cover your classes behind protocols so they are easily testable, just change module registration in your Test project with mocked classes.
- Do not hide class dependencies, you can see all dependencies enlisted in class and recognizable with @Dependency syntax.
- You don't have to write singletons with
class.shared.func
syntax anymore, register class as singleton and just call the variableclass.func
, DI will take care of object life-cycle - DI container validates all dependencies right after start and tells you whether they all can be constructed
See this short yet informative article on medium.com about solid principles.
LightIoC is available through CocoaPods. To install it, simply add the following line to your Podfile:
pod 'LightIoC'
There are tests included covering whole framework as example, clone the repo, and run pod install
. Then you can run test scheme LightIoC-Example
.
// Your protocol
protocol SingletonService {
var id: String { get }
}
// Your class to be injected
class Singleton: SingletonService {
let id: String = "singleton id"
}
// All registrations are in modules so you can separate layer/framework specific services
struct DatabaseLayerModule: IoCModule {
func register(container: IoCContainer) {
do {
try container.registerSingleton(SingletonService.self, Singleton())
} catch {
// Handle error
}
}
}
2) Register modules in app project on startup, for example in AppDelegate, but anywhere else before first dependency is requested
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
IoC.register(module: DatabaseLayerModule())
// IoC.register(module: BusinessLayerModule())
// etc...
return true
}
}
class ViewController: UIViewController {
@Dependency var singleton: SingletonService
override func viewDidLoad() {
super.viewDidLoad()
print(singleton.id)
// result: "singleton id"
}
}
You can overwrite already registered service with another instance/factory by calling IoC.registerAndOverwrite(module:)
. Let's say you are writing tests and you want to change instance of database servis for mock service, so in your test just register another modul conforming to IoCOverwriteModule
with both register and overwrite functions:
class MockSingleton: SingletonService {
let id: String = "mock singleton id"
}
struct MockDatabaseLayerModule: IoCOverwriteModule {
func register(container: IoCContainer) {
do {
try container.overwriteSingleton(SingletonService.self, MockSingleton())
} catch {
// Handle error
}
}
}
IoC.registerAndOverwrite(module: MockDatabaseLayerModule())
All resolves are thread-safe, the access to internal collections is synchronized.
>=Swift 5.1
Ondrej Pisin, [email protected]
LightIoC is available under the MIT license. See the LICENSE file for more info.