SwiftDependencyInjection 1.3

SwiftDependencyInjection 1.3

测试已测试
语言语言 SwiftSwift
许可证 MIT
发布最后发布2024年1月
SPM支持 SPM

Martin Eberl 维护。



  • 作者
  • Martin Eberl

SwiftDependencyInjection




示例

要运行示例项目,克隆仓库,然后首先从 Example 目录运行 pod install

要求

安装

SwiftDependencyInjection 通过 CocoaPods 提供。要安装
它,只需将以下行添加到您的 Podfile 中

pod 'SwiftDependencyInjection'

作者

Martin Eberl, [email protected]

许可证

SwiftDependencyInjection 在 MIT 许可证下提供。有关更多信息,请参阅 LICENSE 文件。

使用

  1. 实现模块
import SwiftDependencyInjection

protocol FooProvider {
    var foo: Foo { get }
}

final class FooModule: Module, FooProvider {
    weak var delegate: ModuleDelegate?

    lazy var foo: Foo = {
        return Foo()
        }()
}

使用协议(此处为 FooProvider)来帮助进行通信和请求注入类型。

  1. 请求协议的实现(例如在您的 ViewController 或任何其他视图模型中)
Injector.shared.inject(self).with(FooProvider.self)

这有助于注入器为您提供所需的依赖项。添加 .with(…Provider.self) 以请求更多依赖项。

  1. 实现 Injectable 协议
func inject(inject: Any) {
    if let inject = inject as? FooProvider {
        foo = inject.foo
    }
}

模块依赖项

假设一些模块需要请求其他模块的依赖项。您可能希望注入器完成这项艰难的工作并解决这些依赖项。

这里有一个 LectureProvider,它向学生提供讲座的存储库。

import SwiftDependencyInjection

protocol LectureProvidable {
    var repository: LectureRepository { get }
}

final class LectureProviderModule: Module, LectureProvidable {
    weak var delegate: ModuleDelegate?

    //lazy makes a var to a singleton
    lazy var repository: LectureRepository = {
        return LectureRepository()
    }()
}

现在根据我们学生的数量,我们想得到一个房间,或者在音乐厅仍然过于拥挤的情况下,我们需要在户外举行讲座

enum Room: Int {
    case lectureRoom = 20
    case lectureHall = 50
    case auditorium = 300

    statuc func for(_ numberOfStudents: Int) -> Room? {
        if numberOfStudents <= Room.lectureRoom.rawValue {
            return .lectureRoom
        }
        if numberOfStudents <= Room.lectureHall.rawValue {
            return .lectureHall
        }
        if numberOfStudents <= Room.lectureHall.rawValue {
            return .auditorium
        }
        return nil
    }

    func holdLecture(_ lector: Lector) {} 
}

import SwiftDependencyInjection

protocol RoomProvidable {
    func room(for lectureId: String) -> Room?
}

final class RoomProviderModule: Module, RoomProvidable {
    weak var delegate: ModuleDelegate?
    weak var lectureRepository: LectureRepository?

    init() {
        //this is how you tell the the Injector, what types of provideables are
        //required for e.g. the RoomProvideable
        //The Roomprovideable is not being provided, unless it's dependencies can 
        //be resolved
        requires(for: RoomProvidable)?
            .this(LectureProvidable.self)
          //.this(... .self) we would add here more dependencies if we needed to
    }

    func room(for lectureId: Int) -> Room? {
        guard let lecture = lectureRepository.lectures(with: lectureId) else {
            return nil
        }
        return Room.for(lecture.subscibedStudents)
    }

    func inject(inject: Any) {
        if let inject = inject as? LectureProvidable {
            lectureRepository = inject.repository
        }
    }
}

现在我们需要注册模块

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.

        //we wont to register the Moduels
        //The Injector has a built in dependency resolve, 
        //so it resolved the conflict, that the RoomProvider is 
        //first instantiated, even though it needs the LecutureProvider Module.
        //When the LectureProviderModule provides it's Provideables, the RoomProvider is
        //automatically injected with the required dependencies
        RoomProviderModule().provide()
        LectureProviderModule().provide()
        
        return true
    }
    ...
}

最后,我们希望讲师提供讲座,学生可以注册,并且应根据学生数量自动选择房间

final class Lector {
    var roomProvidable: RoomProvidable?
    var lectureProvidable: LectureProvidable?

    init() {
        //That's how you say, what dependencies you need
        Injector.shared.inject(self)
            .with(RoomProvidable.self)
            .with(LectureProvidable.self)
    }

    //this is required, because that's how the Injector assigns the dependencies
    func inject(inject: Any) {
        if let inject = inject as? RoomProvidable {
            roomProvidable = inject
        }
        if let inject = inject as? LectureProvidable {
            lectureProvidable = inject
        }
    }

    func provideLecture(lectureId: Int) {
        guard let lectureProvidable = lectureProvidable else {
            return
        }
        lectureProvideable.provide(Lecture(id: lectureId, lector: this, Date(2017, 12, 03), estimatedHours: 2))
    }

    func holdLecture(lectureId: Int) {
        guard let roomProvidable = roomProvidable,
            let room = roomProvidable.room(for: lectureId) else {
            //hold lecture outside
            return
        }
        room.holdLecture(this)
    }
}

1.2.0 版本新增功能

类注入
仅用几行代码,您就可以更轻松地添加依赖项

private var fooProvider = Inject<FooProvider>()

...

fooProvider.value

如果您需要任何其他示例或有改进建议,我将不胜感激