Swinject 2.9.1

Swinject 2.9.1

测试已测试
语言语言 SwiftSwift
许可证 MIT
发布最新发布2024年6月
SPM支持 Swift Package Manager (SPM)

Jakub VanoTomas KohoutMark DiFrancoYoichi TagayaMaxim Chipeev 等维护。



Swinject 2.9.1

  • Swinject 贡献者

Swinject

Travis CI Com Github Actions Carthage compatible CocoaPods Version License Platforms Swift Version Reviewed by Hound

Swinject 是一个用于 Swift 的轻量级 依赖注入 框架。

依赖注入(DI)是一种软件设计模式,它通过控制反转(IoC)来解决依赖问题。在该模式中,Swinject 帮助您将应用程序拆分为松散耦合的组件,这使得开发、测试和维护变得更加容易。Swinject 通过 Swift 的泛型和一等函数来定义应用程序的依赖关系,使其简单且流畅。

功能

扩展

需求

  • iOS 9.0+ / macOS 10.10+ / watchOS 2.0+ / tvOS 9.0+
  • Xcode 10.2+
  • Swift 4.2+
  • Carthage 0.18+(如果您使用的话)
  • CocoaPods 1.1.1+(如果您使用的话)

安装

Swinject可以通过CarthageCocoaPodsSwift包管理器获取。

Carthage

要使用Carthage安装Swinject,请将以下行添加到您的Cartfile中。

github "Swinject/Swinject"

# Uncomment if you use SwinjectStoryboard
# github "Swinject/SwinjectStoryboard"

然后运行carthage update --no-use-binaries命令,或者直接运行carthage update。有关Carthage的安装和使用详情,请访问其项目页面

CocoaPods

要使用CocoaPods安装Swinject,请将以下行添加到您的Podfile中。

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '9.0' # or platform :osx, '10.10' if your target is OS X.
use_frameworks!

pod 'Swinject'

# Uncomment if you use SwinjectStoryboard
# pod 'SwinjectStoryboard'

然后运行pod install命令。有关CocoaPods的安装和使用详情,请访问其官方网站

Swift包管理器

Package.swift中添加以下内容

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"]
    )
    ...
]

文档

基本用法

首先将一个服务和组件对注册到 Container 中,其中组件由注册的闭包创建。在这个例子中,CatPetOwner 分别是实现 AnimalPerson 服务协议的组件类。

let container = Container()
container.register(Animal.self) { _ in Cat(name: "Mimi") }
container.register(Person.self) { r in
    PetOwner(pet: r.resolve(Animal.self)!)
}

然后从容器中获取一个服务实例。将人解析为宠物主人,与叫做咪咪的猫玩耍!

let person = container.resolve(Person.self)!
person.play() // prints "I'm playing with Mimi."

协议和类的定义如下

protocol Animal {
    var name: String? { get }
}

class Cat: Animal {
    let name: String?

    init(name: String?) {
        self.name = name
    }
}

protocol Person {
    func play()
}

class PetOwner: Person {
    let pet: Animal

    init(pet: Animal) {
        self.pet = pet
    }

    func play() {
        let name = pet.name ?? "someone"
        print("I'm playing with \(name).")
    }
}

注意,当将 Person 解析为 PetOwner 的实例时,PetOwnerpet 会自动设置为 Cat 的实例。如果提供了一个已经设置好的容器,你就不必关心服务的实际类型以及如何带有它们的依赖来创建。

服务注册位置

在使用之前,必须将服务注册到容器中。典型的注册方法将取决于你是否使用 SwinjectStoryboard

以下视图控制器类在下面的例子中除了上面的协议和类外还会使用。

class PersonViewController: UIViewController {
    var person: Person?
}

使用 SwinjectStoryboard

在Swift源文件顶部导入 SninjectStoryboard。

import SwinjectStoryboard

如果你使用 SwinjectStoryboard,应该在 SwinjectStoryboard 的扩展中将服务注册。有关详细说明,请参阅 SwinjectStoryboard 的项目页面

extension SwinjectStoryboard {
    @objc class func setup() {
        defaultContainer.register(Animal.self) { _ in Cat(name: "Mimi") }
        defaultContainer.register(Person.self) { r in
            PetOwner(pet: r.resolve(Animal.self)!)
        }
        defaultContainer.register(PersonViewController.self) { r in
            let controller = PersonViewController()
            controller.person = r.resolve(Person.self)
            return controller
        }
    }
}

不使用SwinjectStoryboard

如果您没有使用SwinjectStoryboard来实例化视图控制器,则应在应用程序的AppDelegate中将服务注册到容器中。在application:didFinishLaunchingWithOptions:退出之前注册将确保在它们被使用之前适当设置服务。

class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
    let container: Container = {
        let container = Container()
        container.register(Animal.self) { _ in Cat(name: "Mimi") }
        container.register(Person.self) { r in
            PetOwner(pet: r.resolve(Animal.self)!)
        }
        container.register(PersonViewController.self) { r in
            let controller = PersonViewController()
            controller.person = r.resolve(Person.self)
            return controller
        }
        return container
    }()

    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {

        // Instantiate a window.
        let window = 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)

        return true
    }
}

注意,示例使用了一个便利初始化器,它接受一个闭包将该服务注册到Container的新实例。

在Playground中播放!

该项目包含Sample-iOS.playground以展示Swinject的功能。下载或克隆项目,运行playground,对其进行修改,并玩起来,以了解Swinject。

要在项目中共跑playground,首先构建项目,然后在Xcode中选中编辑 > 执行Playground菜单。

示例应用

可以在GitHub上找到一些使用Swinject的示例应用。

博客文章

以下博客文章介绍了依赖注入和Swinject的概念。

感谢作者们的贡献!

贡献指南

关于提交问题、提问或者开启pull请求的指南,请参见这里

有问题?

致谢

Swinject的依赖注入容器特性受到以下项目的启发

以及高度受到以下项目的启发

许可证

MIT许可证。有关详情,请参阅LICENSE文件