1

UITableViewControllerie: という名前のクラスのインスタンスをdidSelectRowAtSectionロードする があり、それが のプロパティを持っているため、プロパティインジェクションClassToInjectを介してそれを注入しようとしていると仮定しましょう。次のように単純に準拠します。ViewControllerToBePushedClassToInjectUITabBarViewControllerdidSetviewControllersClassToInjectPresentable

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)
    }
}
4

2 に答える 2

1

最後に、提案された提案に従って、最終的な答えを得ました。

public class Containers {
    fileprivate init() { }
}

extension Containers {
    static let activityPresentableContainer: Container = {
        let container = Container()
        container.register(ActivityTabBarController.self) { (r: Resolver, arg1: Activity) in
            return ActivityTabBarController(activity: arg1)
        }
        container.register(ActivityPresentable.self) {
           (r: Resolver, arg1: ActivityPresentableTabs, arg2: Activity) in
           switch arg1 {
           case .summary:
               return ActivitySummaryViewController(activity: arg2)
           case .detail:
               return ActivityDetailPageViewController(activity: arg2)
           case .map:
               return ActivityMapViewController(activity: arg2)
           case .charts:
               return ActivityChartsViewController(activity: arg2)
           case .strava:
              return ActivityStravaViewController(activity: arg2)
           }
        }.inObjectScope(.transient)
       return container
    }()

このアプローチでは、名前付きは常に次のステートメントを使用してActivityTabBarControllerインスタンス化されます。activityPresentableContainer

let controller = Containers.activityPresentableContainer.resolve(
    ActivityTabBarController.self, argument: activity
)!

次に、TabBarController 内の各タブはActivity、コンテキストを使用して、必要な引数とタブ自体のタイプを使用してインスタンス化され.transientます。次のように解決します。

let activitySummary = Containers.activityPresentableContainer.resolve(
   ActivityPresentable.self, arguments: ActivityPresentableTabs.summary, activity!
) as! UIViewController

このようにして、使用している情報だけに応じて、タブ バーのタブを一般化できます。いずれかのタブが変更された場合は、ActivityPresentableプロトコルに従って登録を変更できます。

于 2017-06-06T13:41:56.467 に答える