ios - Swinject 将自己的属性注入(inject)新的 UIViewController

标签 ios swift dependency-injection swinject

假设我们有一个 UITableViewController,它在 didSelectRowAtSection 上加载了一个名为即 ClassToInject 的类的实例,它希望通过一个属性注入(inject),因为我们的 ViewControllerToBePushed 有一个属性 ClassToInject,随后(因为它是一个 UITabBarViewController)在 didSet 回调它搜索所有符合 ClassToInjectPresentableviewControllers 属性,简单如下:

protocol ClassToInjectPresentable { 
  var property: ClassToInject { get set } 
}

到现在为止,我只会做这样的事情:

func didSelectRowAtIndexPath {
     let classToInject = self.loadClassToInjectFor(indexPath)
     let tabBarViewController = SomeTabBarViewController()
     tabBarViewController.property = classToInject
     self.navigationController.push(tabBarViewController, animated: true)
}

并且在 SomeTabBarViewController ...

class SomeTabBarViewController: ClassToInjectPresentable {
  var property: ClassToInject? {
  didSet(newValue) {
      self.viewControllers.filter{ $0 is ClassToInjectPresentable }.map{ $0 as! ClassToInjectPresentable }.forEach{ $0.property = newValue }
  }
 }

所有的东西都应该很容易地加载(但事实并非如此)。我读过有关 Swinject 的文章,这可能会用它来解决。我已经看到很多注册示例,例如:

container.register(Animal.self) { _ in Cat(name: "Mimi") }

但我不知道我是否可以注册一些在self中加载的属性:

container.register(ClassToInjectInjector.self) { _ in 
self.loadClassToInjectFor(indexPath) }
// And then
container.register(ClassToInjectPresentable.self) { _ in 
SomeTabBarViewController() }
    .initCompleted { r, p in
        let tabBar = p as! SomeTabBarViewController
        tabBar.property = r.resolve(ClassToInjectInjector.self)
        // And lastly?
        self.navigationController.pushViewController(tabBar, animated: true)
    }
}

最佳答案

在不了解您的应用细节的情况下很难推荐合适的解决方案,但这里有一些建议:

container.register(ClassToInjectInjector.self) { _ in 
    self.loadClassToInjectFor(indexPath) 
}

一般来说,所有的register 操作都应该在你的对象之外完成。常见的设置是拥有一个全局 Container,其中包含所有注册 - 您应该将它们视为在没有任何隐式上下文的情况下构建应用程序对象的说明。如果您的依赖项需要在 UITableViewController 中创建,您可以将其作为参数传递给 resolve 方法:

container.register(ClassToInjectPresentable.self) { resolver, property in
    let tabBar = SomeTabBarViewController()
    tabBar.property = property
    return tabBar
}

// in UItableVIewController
container.resolve(ClassToInjectPresentable.self, 
                  argument: self.loadClassToInjectFor(indexPath))

这通常也是个坏主意:

.initCompleted { r, p in
    ...
    self.navigationController.pushViewController(tabBar, animated: true)
 }

您不应将应用程序逻辑与 DI 混合使用 - 纯粹使用 Swinject 来构建您的依赖项。

所以你的 UITableViewController 可能看起来像这样:

func didSelectRowAtIndexPath {
    let classToInject = self.loadClassToInjectFor(indexPath)
    let tabBar = container.resolve(
        SomeTabBarViewController.self, argument: loadClassToInjectFor(indexPath)
    )
    navigationController.push(tabBar, animated: true)
}

至于您的 TabBar 及其 View Controller :UIViewControllers 如何进入 TabBar?有可能做这样的事情吗?

class SomeTabBarViewController {
    init(viewControllers: [UIViewController]) {
        ...
    }   
}

container.register(SomeTabBarViewController.self) { r, property
    SomeTabBarViewController(viewControllers:[
        r.resolve(MyViewController.self, argument: property),
        r.resolve(MyViewController2.self, argument: property)
    ])
}

关于ios - Swinject 将自己的属性注入(inject)新的 UIViewController,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44356781/

相关文章:

c# - Autofac:注册异步工厂方法

iphone - 如何避免滚动时 UITableViewCell 中的图像被刷新?

ios - 移动和修复手机 iOS 上录制的视频的 moov 原子

ios - 在启用分页的情况下检测 scrollView 中的 y 偏移何时发生变化

iphone - TableView 在 Swift 中推送到详细 View

iOS - 获取容器 View 内容动态高度

ios - 键盘处理就像在 iOS 7 中的消息应用程序中一样

ios - 向 AppDelegate 发送消息不适用于应用内购买

php - 如何避免冲突用于依赖注入(inject)的 PHP 特性

java - Spring - Bean 没有被注入(inject)