我正在使用 MVVM + Coordinators 构建一个新应用程序。具体来说,我使用的是https://github.com/daveneff/Coordinator上的 Coordinator 模式。
在顶层,我有一个 AppCoordinator,可以启动子协调器 RegisterCoordinator。当注册流程完成后,AppCoordinator 会切换其导航器的根视图控制器,注册流程中使用的协调器和视图控制器应该从内存中释放。
final class AppCoordinator: CoordinatorNavigable {
var dependencies: AppDependencies
var childCoordinators: [Coordinator] = []
var rootViewController = UINavigationController()
var navigator: NavigatorType
init(window: UIWindow, dependencies: AppDependencies) {
self.dependencies = dependencies
navigator = Navigator(navigationController: rootViewController)
dependencies.userManager.delegate = self
window.rootViewController = rootViewController
window.makeKeyAndVisible()
}
func start() {
if dependencies.properties[.user] == nil {
// Logged out state
let vc = AuthFlowViewController.instantiate(storyboardName: Constants.Storyboards.authFlow)
vc.delegate = self
navigator.setRootViewController(vc, animated: false)
} else {
// Logged in
let vc = HomeViewController.instantiate(storyboardName: Constants.Storyboards.home)
vc.viewModel = HomeViewModel(dependencies: dependencies)
navigator.setRootViewController(vc, animated: false)
}
childCoordinators = []
}
}
extension AppCoordinator: UserManagerDelegate {
func authStateChanged() {
// User logged in or logged out; show the correct root view controller
start()
}
func userChanged() {}
}
extension AppCoordinator: AuthFlowViewControllerDelegate {
func login() {
dependencies.userManager.changeUser(newUser: User(id: 1, name: "Kevin"))
}
func startRegisterFlow() {
let registerCoordinator = RegisterCoordinator(dependencies: dependencies, navigator: navigator)
pushCoordinator(registerCoordinator, animated: true)
}
}
RegisterCoordinator 同时简单地将多个视图控制器推送到导航器的堆栈中:
class RegisterCoordinator: CoordinatorNavigable {
var dependencies: AppDependencies
var childCoordinators: [Coordinator] = []
var navigator: NavigatorType
let rootViewController = PhoneInputViewController.instantiate(storyboardName: Constants.Storyboards.authFlow)
init(dependencies: AppDependencies, navigator: NavigatorType) {
self.dependencies = dependencies
self.navigator = navigator
rootViewController.delegate = self
}
func start() {}
}
extension RegisterCoordinator: PhoneInputViewControllerDelegate {
func phoneInputDone() {
let vc = PhoneValidationViewController.instantiate(storyboardName: Constants.Storyboards.authFlow)
vc.delegate = self
navigator.push(vc, animated: true)
}
}
extension RegisterCoordinator: PhoneValidationViewControllerDelegate {
func phoneValidationDone() {
let vc = GenderSelectionViewController.instantiate(storyboardName: Constants.Storyboards.authFlow)
vc.viewModel = GenderSelectionViewModel(dependencies: dependencies)
navigator.push(vc, animated: true)
}
}
当整个注册流程完成后,最后一个页面可以保存用户,这会触发authStateChanged
AppCoordinator 中的方法,然后更改导航器的 rootViewController。这也应该清理它的子协调器。
遗憾的是,RegisterCoordinator 及其 rootViewController (PhoneInputViewController) 仍然保持活动状态——尽管流程中的其他视图控制器已正确释放。
我尝试childCoordinators = []
在start
方法中手动执行以确保 AppCoordinator 没有对 RegisterCoordinator 的强引用,但即使这样也无济于事。
我不知道是什么保留了强引用,导致保留周期/内存泄漏。我有一个超级最小版本的应用程序,除了显示问题的基本要素外,基本上所有内容都被删除了,在 GitHub 上:https ://github.com/kevinrenskers/coordinator-problem 。