iOS 的 ServiceLocator

Build GitHub Tag Static Badge Static Badge Static Badge

Service Locator 是一种设计模式,用于将获取对象的方式与实现对象的具体类解耦。 它的实现方式是将对象创建集中到一个位置,称为服务定位器。

这个小项目受到 RouterServiceSwinject 的启发

开始使用

1. 定义依赖注册的模块

模块对相关的服务注册进行分组。 它们重写 build() 方法来定义服务如何向定位器注册。

class MyModule: ServiceLocatorModule {

    override func build() {

        // singletons
        single(ConfigProviderProtocol.self) {
            ConfigProvider()
        }

        // get dependencies with resolve
        single(URLFactory.self) {
            URLFactory(remoteConfigProvider: self.resolve())
        }

        // factory
        factory(AppLinkFactory.self) {
            let settingsManager: SettingsManager = self.resolve()

            return AppLinkFactory(descriptionFactory: settingsManager)
        }
    }
}

提示:定义一个应用程序范围内的模块,其中包含其他模块。

class AppModule: ServiceLocatorModule {

    override func build() {
        module { MyModule() }
    }
}

2. 初始化 Service Locator

lazy var myServiceLocator = startServiceLocator {
    AppModule()
}
myServiceLocator.build()

3. 检索依赖

3.1. 在数据结构中

使用 @Inject 在类或结构体中检索依赖。 属性包装器自动从服务定位器解析依赖

class MyCass {
    @Inject(myServiceLocator) public var contactSheet: ContactSheet
}

3.2 函数中的局部变量注入

对于在函数或方法中注入依赖,请在局部变量声明之前使用 @Inject

func doSomething() {
    @Inject(myServiceLocator) var contactSheet: ContactSheet
    // Use contactSheet here
}

3.3 使用 resolve 直接解析

如果您不喜欢使用属性包装器,请使用服务定位器的 resolve 方法直接解析依赖

let configProvider : ConfigProvider = serviceLocator.resolve()

4. 重置 Service Locator

您可以将 ServiceLocator 重置为其初始状态,这在测试场景中非常有用

// Reset the entire service locator
resetServiceLocator(myServiceLocator)

// Or, if you have direct access to the ServiceLocator instance:
myServiceLocator.reset()

提示和自定义

自定义属性包装器

如果您有特定需求或想简化特定范围的用法(例如本例中的插件),请创建定制的属性包装器

@propertyWrapper
internal final class PluginInject<T>: Dependency<T> {

    public var wrappedValue: T {
        resolvedWrappedValue()
    }

    public init() {
        super.init(MyPlugin.shared.myServiceLocator)
    }
}

用法

class MyClass {
    @PluginInject var contactSheet: ContactSheet
}
func doSomething() {
    @PluginInject var contactSheet: ContactSheet
}

启用日志记录

您可以为 ServiceLocator 启用日志记录,以帮助进行调试

ServiceLocator.enableLogging = true

如何安装

Swift Package Manager

将依赖项添加到您的 Package.swift

    products: [
      ...
    ]
    dependencies: [
        .package(url: "https://github.com/kibotu/ServiceLocator", from: "1.0.2"),
    ],
    targets: [
      ...
    ]

要求

欢迎贡献!

许可证

Copyright 2024 Jan Rabe & CHECK24

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   https://apache.ac.cn/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.