gpt4 book ai didi

ios - 使用协调器模式时奇怪的保留周期

转载 作者:行者123 更新时间:2023-11-28 13:32:44 24 4
gpt4 key购买 nike

我正在使用 MVVM + 协调器构建一个新应用。具体来说,我正在使用在 https://github.com/daveneff/Coordinator 上找到的协调器模式.

在顶层,我有一个 AppCoordinator,它可以启动子协调器 RegisterCoordinator。注册流程完成后,AppCoordinator 会切换其导航器的 Root View Controller ,注册流程中使用的协调器和 View Controller 应从内存中释放。

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 简单地将多个 View Controller 推送到导航器的堆栈上:

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

当整个注册流程完成后,最后一个页面可以保存用户,这会触发 AppCoordinator 中的 authStateChanged 方法,然后更改导航器的 rootViewController。这也应该清理它的子协调器。

遗憾的是,RegisterCoordinator 及其 rootViewController (PhoneInputViewController) 保持事件状态 - 尽管流中的其他 View Controller 已正确释放。

我尝试在 start 方法中手动执行 childCoordinators = [] 以确保 AppCoordinator 没有对 RegisterCoordinator 的强引用,但即便如此'帮助。

我不知道是什么保留了强引用,导致了保留周期/内存泄漏。我的应用程序有一个 super 最小版本,除了显示问题的基本要素外,基本上删除了所有内容,在 GitHub 上:https://github.com/kevinrenskers/coordinator-problem .

最佳答案

首先,您在 Coordinator.self 第 132 行的一个 block 中捕获协调器:

enter image description here

我使用 Debug Memory Graph 发现了这个:

enter image description here

还有 PhoneInputViewController 还活着,你可以检查为什么使用相同的方法

我不能完全理解你的协调器模式实现是如何工作的,但最好不要对你的 Controller 保持强引用。

我一直在使用一些实现,其中 Controller 仅由 UINavigationController 的堆栈保留,而 window 保留 UINavigationController

它保证您的 Controller 在弹出/替换后总是死掉。

在你的情况下,我会首先尝试制作 CoordinatorchildCoordinators 以保持对你的 Controller 的弱引用。

关于ios - 使用协调器模式时奇怪的保留周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57112264/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com