JGu*_*Guo 7 factory dependency-injection circular-dependency swift
我正在关注 John Sundell 的帖子以实现导航器模式(https://www.swiftbysundell.com/posts/navigation-in-swift)。基本思想是,与 Coordinator 模式相比,每个视图控制器可以简单地调用,navigator.navigate(to: .someScreen)而不必知道其他视图控制器。
我的问题是,因为为了构造一个视图控制器我需要一个导航器,为了构造一个导航器我需要一个导航控制器,但我想让视图控制器成为导航控制器的根,解决这个问题的最佳方法是什么以一种尊重依赖注入最佳实践的方式循环依赖?
下面是 Sundell 说明的导航器模式的想法
protocol Navigator {
associatedtype Destination
func navigate(to destination: Destination)
}
class LoginNavigator: Navigator {
enum Destination {
case loginCompleted(user: User)
case signup
}
private weak var navigationController: UINavigationController?
private let viewControllerFactory: LoginViewControllerFactory
init(navigationController: UINavigationController,
viewControllerFactory: LoginViewControllerFactory) {
self.navigationController = navigationController
self.viewControllerFactory = viewControllerFactory
}
func navigate(to destination: Destination) {
let viewController = makeViewController(for: destination)
navigationController?.pushViewController(viewController, animated: true)
}
private func makeViewController(for destination: Destination) -> UIViewController {
switch destination {
case .loginCompleted(let user):
return viewControllerFactory.makeWelcomeViewController(forUser: user)
case .signup:
return viewControllerFactory.makeSignUpViewController()
}
}
}
Run Code Online (Sandbox Code Playgroud)
class LoginViewController: UIViewController {
private let navigator: LoginNavigator
init(navigator: LoginNavigator) {
self.navigator = navigator
super.init(nibName: nil, bundle: nil)
}
private func handleLoginButtonTap() {
navigator.navigate(to: .loginCompleted(user: user))
}
private func handleSignUpButtonTap() {
navigator.navigate(to: .signup)
}
}
Run Code Online (Sandbox Code Playgroud)
现在AppDelegate我想做一些类似的事情
let factory = LoginViewControllerFactory()
let loginViewController = factory.makeLoginViewController()
let rootNavigationController = UINavigationController(rootViewController: loginViewController)
window?.rootViewController = rootNavigationController
Run Code Online (Sandbox Code Playgroud)
但是我必须以某种方式将 the 传递给rootNavigationControllerthefactory以便loginViewController正确构造它,对吗?因为它需要一个导航器,它需要导航控制器。怎么做?
这能解决问题吗?在应用程序委托中:
let factory = LoginViewControllerFactory()
let navController = UINavigationController()
let loginNavigator = LoginNavigator(navigationController: navController, viewControllerFactory: factory)
loginNavigator.navigate(to: .signup) // The example doesn't have a .login Destination, but it can easily be added to the factory, so using .signup instead
window?.rootViewController = navController
Run Code Online (Sandbox Code Playgroud)