代替使用子协调器,您可以编写您的协调器类,使它们根本不需要保留。实际上,在您给出的示例中,没有什么需要保留此类,您甚至可以将其最小化为以下形式:
class InStoreMainCoordinator {
func start(with navigationController: UINavigationController, container: Container) {
let inStoreMainViewModel = InStoreMainViewModel()
let inStoreMainController = InStoreMainController()
inStoreMainController.viewModel = inStoreMainViewModel
navigationController.pushViewController(inStoreMainController, animated: true)
}
}
然后InStoreMainCoordinator().start(with: navigationController, container: container)
在您想要启动此屏幕时调用。您根本不需要保留对此 InStoreMainCoordinator 的强引用。这样您就不会对后退按钮有任何问题,因为您不需要解除分配这些协调器。它们仅在您将屏幕切换到新屏幕时才存在。为了更好地理解此方法,假设您有另一个屏幕,例如 InStoreDetailsController 类,并且在单击 InStoreMainController 上的某些内容后应该启动详细信息屏幕。然后你可以实现两个与这些视图控制器相关的协调器类,如下所示:
class InStoreMainCoordinator {
func start(with navigationController: UINavigationController, container: Container) {
let inStoreMainViewModel = InStoreMainViewModel(onStoreSelected: { storeId in
InStoreDetailsCoordinator().start(with: navigationController, container: container, dependencies: .init(storeId: storeId))
})
let inStoreMainController = InStoreMainController()
inStoreMainController.viewModel = inStoreMainViewModel
navigationController.pushViewController(inStoreMainController, animated: true)
}
}
class InStoreDetailsCoordinator {
struct Dependencies {
var storeId: String
}
func start(with navigationController: UINavigationController, container: Container, dependencies: Dependencies) {
let inStoreDetailsViewModel = InStoreDetailsViewModel(storeId: dependencies.storeId)
let inStoreDetailsController = InStoreDetailsController()
inStoreDetailsController.viewModel = inStoreDetailsViewModel
navigationController.pushViewController(inStoreDetailsController, animated: true)
}
}
正如您所看到的,如果您使用闭包而不是委托模式,您可以在单个函数中编写与一个屏幕相关的所有内容(包括将其推送到屏幕上并处理与例如从该屏幕移动到另一个屏幕相关的事件)。这样,您在需要切换屏幕时调用的协调器中的每个屏幕只有一个方法,并且您不需要保留它们,因为需要保留的所有内容都由其他东西保留(在上面的示例中,视图模型保留onStoreSelected 参数中给出的处理程序,用于切换到另一个屏幕)。我认为这个解决方案比使用儿童协调员更简单。它工作正常,不需要对后退按钮进行任何额外的特殊处理。
另一种可以很好地工作的替代解决方案,特别是如果您的应用程序中没有大量的屏幕,是为您的主AppCoordinator类或您命名的任何视图控制器中的每个视图控制器创建startNameOfYourScreen(...)方法。正如您在上面看到的,如果您使用闭包而不是委托模式,您可以在一个函数中编写与一个屏幕相关的所有内容,这样可以保持非常简单。您可以选择将这些函数拆分为AppCoordinator类的扩展,并将它们放入单独的文件中,以便在您的项目中有更好的组织。在此解决方案中,后退按钮也没有任何问题,因为您根本不需要实例化子协调器,也不需要解除分配它们。
但是,如果由于某种原因您决定仍要使用子协调员的方式,那么这里有一些关于在使用子协调员时可能解决后退按钮问题的文章的链接供参考: