ios - 如何使用 swinject 正确注入(inject)依赖项

标签 ios swift dependency-injection swinject

我正在尝试使用 Swinject 注入(inject)依赖项,但我不知道我做错了什么。

我有处理注册用户的协议(protocol)。

protocol AuthServiceProtocol {
func registerUser(email: String, password: String, completion: @escaping CompletionHandler) }

并且符合此协议(protocol)的类完成所有逻辑:

class AuthService: AuthServiceProtocol {
func registerUser(email: String, password: String, completion: @escaping CompletionHandler) {

        let lowerCaseMail = email.lowercased()
        let body: [String: Any] = [
            "email": lowerCaseMail,
            "password" : password
        ]

        Alamofire.request(URL_REGISTER, method: .post, parameters: body, encoding: JSONEncoding.default, headers: HEADER).responseString { (response) in
            if response.result.error == nil {
                completion(true)
            } else {
                completion(false)
                debugPrint(response.result.error as Any)
            }
        }
    }
} 

所以,在 AppDelegate 中我们注册容器,它看起来像:

let container = Container() { container in
    container.register(AuthServiceProtocol.self) { _ in AuthService() }.inObjectScope(.container)
    container.register(CreateAccountVC.self) { r in
        let controller = CreateAccountVC()
        controller.authService = r.resolve(AuthServiceProtocol.self)
        return controller
    }
}

但是在CreateAccountVC authService 中是空的。有什么想法我该怎么做吗? CreateAccountVC是ViewController的子类,我已经通过属性和构造函数尝试过它,但它始终为零。

最佳答案

检查您的代码:

var container : Container {
        let container = Container()
        container.register(AuthServiceProtocol.self) { _ in AuthService() }.inObjectScope(.container)
        container.register(CreateAccountVC.self) { r in
            let controller = CreateAccountVC()
            controller.authService = r.resolve(AuthServiceProtocol.self)
            print(r.resolve(AuthServiceProtocol.self))
            return controller
        }

        return container
    }

您有计算属性,每次调用它时,它都会创建一个新的容器对象。

重构您的代码以拥有单个容器,我相信您会很顺利。


编辑:

这是一个有效的代码片段。 下面是一个小包装类,用于抽象具体的 DI 服务(以防 Swinject 有一天被其他东西替换):

import Swinject

public class ConfigurationProvider {

    // Currently using Swinject
    private let backingService = Container()

    // Singleton
    public static let shared = ConfigurationProvider()

    // Hidden initializer
    private init() {}


    // MARK: - Bind / Resolve

    public func bind<T>(interface: T.Type, to assembly: T) {
        backingService.register(interface) { _ in assembly }
    }

    public func resolve<T>(interface: T.Type) -> T! {
        return backingService.resolve(interface)
    }
}


// Extension methods to ignore 'shared.' call, like:
// ConfigurationProvider.bind(interface: IAssembly, to: Assembly())
// ConfigurationProvider.resolve(interface: IAssembly)

public extension ConfigurationProvider {

    static func bind<T>(interface: T.Type, to assembly: T) {
        ConfigurationProvider.shared.bind(interface: interface, to: assembly)
    }

    static func resolve<T>(interface: T.Type) -> T! {
        return ConfigurationProvider.shared.resolve(interface: interface)
    }
}

用法:

class RSAuthLoginModuleAssembly: IAuthLoginModuleAssembly {

}

// Register:

ConfigurationProvider.bind(interface: IAuthLoginModuleAssembly.self, to: ConcreteAuthLoginModuleAssembly())

// Resolve:

    guard let assembly = ConfigurationProvider.resolve(interface: IAuthLoginModuleAssembly.self) else {
        throw NSError(domain: "Assembly cannot be nil", code: 999, userInfo: nil)
    }

关于ios - 如何使用 swinject 正确注入(inject)依赖项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46768990/

相关文章:

ios - UILabel 动画宽度

ios - 自定义 Collection View 单元格在点击时消失

ios - 如何使用结构更新 Firebase

asp.net-mvc - 在服务层使用HttpContextBase

java - 如何在某些 Spring 测试中注入(inject)类的特定实例?

ios - 如何在运行 VoiceOver 时实现像 Podcast 应用程序这样的可拖动洗涤器?

ios - 无法运行 Appium 服务器

ios - 设置时更改类属性

xml - IoC/依赖注入(inject) - 请解释代码与 XML

iOS 12 推送通知在以下版本中不起作用,在 iOS 12 中未收到推送通知