아직 Swift에서는 DI 라이브러리를 많이 쓰이고 있진 않은 것 같다. github에 DI 라이브러리들이 몇몇 개 보이긴 하는데, Singleton을 지원하지 않거나 class를 key로 쓰고 있어 같은 타입의 object를 등록할 수 없는 등 불편한 점들이 여럿 있었다. 그래서 이런것들을 개선하여 필요한 기능들만 간단하게 만들어 쓰고 있었는데, 여러 프로젝트에 쓰다보니 코드 관리의 필요성이 생겨 라이브러리화 하여 github에 업로드 하였다.
github: https://github.com/ezero9/SwiftInjection
Class Summary
Class DIContainer
func configure()
func resolve<T>() -> T
func resolve<T>(key: String) -> T
func contains(key: String) -> Bool
func register<T>(_ assemble: @escaping () -> T)
func register<T>(key: String, _ assemble: @escaping () -> T)
func registerSingleton<T>(_ assemble: @escaping () -> T)
func registerSingleton<T>(key: String, _ assemble: @escaping () -> T)
func registerSingleton<T>(key: String, value: T)
func destroy()
Class DIContainerManager
func registerContainer<T>(container: T)
func getObject<T>(key: String) -> T
func resolve<T>() -> T
func destroy()
Usage
1. Register class
class를 등록하는 방법은 아래 [코드 1]처럼 DIContainer를 상속받아 configure를 override하여 사용하는 방법과 [코드 2]와 같이 DIContainer를 직접 사용하는 방법이 있다.
// DIContainer를 상속 받아 configure를 override하여 사용하는 방법 | |
class MyContainer: DIContainer { | |
override func configure() { | |
registerSingleton { Earth() } | |
register { Book() } | |
register { Pen() } | |
register { PencilCase(pen: self.resolve()) } | |
register { Bag(pencilCase: self.resolve(), book: self.resolve()) } | |
register { Human(bag: self.resolve()) } | |
register(key: "happy") { Dog(name: "happy") } | |
register(key: "goofy") { Dog(name: "goofy") } | |
} | |
} |
[코드 1]
let myContainer = DIContainer() | |
myContainer.registerSingleton { Earth() } | |
myContainer.register { Book() } |
[코드 2]
2. Get object
등록된 class는 아래 [코드 3]과 같이 오브젝트를 생성할 수 있다.
//1. let myContainer = MyContainer() | |
//2. let myContainer = DIContainer() | |
let human: Human = myContainer.resolve() |
[코드 3]
3. Manage container
관심사에 따라 여러 컨테이너를 작성하여 물리적으로 분리하고 아래 [코드 4]와 같이 DIContainerManager에 등록하여 사용 할 수 있다. 그리고 상황에 따라 container들을 다르게 생성하여 다른 행동을 하도록 Strategy pattern을 적용할 수 있다.
let containerManager = DIContainerManager() | |
#if DEBUG | |
containerManager.registerContainer(container: testServiceAContainer) | |
containerManager.registerContainer(container: testServiceBContainer) | |
#else | |
containerManager.registerContainer(container: serviceAContainer) | |
containerManager.registerContainer(container: serviceBContainer) | |
#endif | |
let human: Human = containerManager.resolve() |
[코드 4]
'iOS' 카테고리의 다른 글
Swift에서의 AOP (0) | 2020.08.03 |
---|---|
Realm은 thread safe하지 않다. (0) | 2019.09.01 |
SwiftUI Bata 하루 사용해본 후기 (0) | 2019.08.17 |