【问题标题】:How to proper inject dependency using swinject如何使用 swinject 正确注入依赖项
【发布时间】:2017-10-16 11:13:32
【问题描述】:

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

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

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

和一个符合这个协议的类组成了所有的逻辑:

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 的子类,我已经通过属性和构造函数尝试过它,但它一直是 nil。

【问题讨论】:

    标签: ios swift dependency-injection swinject


    【解决方案1】:

    检查您的代码:

    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
        }
    

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

    重构您的代码以拥有一个 Container,我相信您会很顺利。


    编辑:

    这是一个工作代码 sn-p。 下面是一个用于抽象具体 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)
        }
    

    【讨论】:

    • 好的,如果我理解我必须调用在应用程序的整个生命周期中创建一个容器的函数?
    • 没错。您为/从特定的 Container 对象注册/解析。
    • 您现在可以检查容器代码吗?我只实例化了一次,它仍然是 nil..
    • 你能分享一下你解析对象并返回 nil 的代码吗?
    • 所以如果我在容器中解决它,并在一行中覆盖它是不好的?我还应该在其他任何地方解决它吗? CreateAccountVC 中的 authService 是公开的。
    猜你喜欢
    • 2012-05-27
    • 2020-05-11
    • 1970-01-01
    • 1970-01-01
    • 2021-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多