I try to implement some variant of Coordinator pattern, but I face problem with retain cycle in closure. It looks like that:
func goTo() {
let coord = SecondViewCoordinator(nav: navigationController)
add(coord)
coord.start()
coord.deinitIfNeeded = { [weak self] in
guard let self = self else { return }
self.free(coord)
}
}
As you can see I set deinitIfNeeded
and then, if in SecondViewCoordinator
call deinitIfNeeded?()
controller pops correctly, but reference to SecondViewCoordinator
is still exist even though childCoordinators
array is empty.
My Coordinator class looks like that:
class Coordinator {
weak var navigationController: UINavigationController?
var childCoordinators: [Coordinator] = []
var deinitIfNeeded: (() -> ())?
init(nav: UINavigationController?) {
self.navigationController = nav
}
func add(_ coordinator: Coordinator) {
childCoordinators.append(coordinator)
}
func free(_ coordinator: Coordinator) {
childCoordinators = childCoordinators.filter({ $0 !== coordinator })
}
}
memory graph presents this:
any ideas?
In
coord.deinitIfNeeded = { [weak self] in
guard let self = self else { return }
self.free(coord)
}
You are holding a strong reference to coord
inside the closure. Try something like this;
coord.deinitIfNeeded = { [weak self, weak coord] in
guard let self = self, let coord = coord else { return }
self.free(coord)
}
The memory graph is giving a hint that this is the case (the right side says the strong reference is in a closure).
You could also set coord.deinitIfNeeded
to nil
inside the closure.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.