函数内部函数保留周期
Function inside Function retain cycle
我想知道在以下情况下如何避免保留周期:
private func setupDismissCallbacks() {
// inner func
func dismiss() {
self.videoExporter?.cancel()
self.rootViewController.dismiss(animated: true, completion: nil)
self.delegate?.childCoordinatorDidFinish(self)
}
// first clousre
saveModalViewController.onButtonDismiss = { [weak self] in
// not really using `self` here
guard let self = self else { return }
dismiss()
}
// second clousre
saveModalViewController.onDimmedAreaDismiss = { [weak self] in
// not really using `self` here
guard let self = self else { return }
dismiss()
}
}
我有一个函数 setupDismissCallbacks
,它监听来自 saveModalViewController
自身 属性 的两个回调。 dismiss()
是 setupDismissCallbacks
中的一个内部函数,我用它来访问 self
值。
但是在闭包 onButtonDismiss
和 onDimmedAreaDismiss
中,我无法访问 self 来调用 dismiss
,而且我无法将 [weak self]
添加到 dismiss
函数,因为它是一个函数。
如何验证 dismiss
中的调用不会导致保留循环?
@Alexander 在评论中解释了这个问题:
Your inner function captures self
. Your two closures capture that
inner function (including the context it encloses over, which includes
self
). Since your two closures are strongly referenced by
saveModalViewController
(which I assume is strongly referenced by
self
), you have a retain cycle.
您可以通过不让 dismiss
捕获 self
来打破这个循环。将 SaveCoordinator
传递给 dismiss
:
private func setupDismissCallbacks() {
func dismiss(_ coordinator: SaveCoordinator) {
coordinator.videoExporter?.cancel()
coordinator(animated: true, completion: nil)
coordinator.delegate?.childCoordinatorDidFinish(coordinator)
}
// first clousre
saveModalViewController.onButtonDismiss = { [weak self] in
guard let self = self else { return }
dismiss(self)
}
// second clousre
saveModalViewController.onDimmedAreaDismiss = { [weak self] in
guard let self = self else { return }
dismiss(self)
}
}
只需将闭包分配给局部变量即可。那时,提取 dismiss
是没有意义的,所以直接内联它:
private func setupDismissCallbacks() {
let dismissCallback: () -> Void = { [weak self] in
guard let self = self else { return }
self.videoExporter?.cancel()
self.rootViewController.dismiss(animated: true, completion: nil)
self.delegate?.childCoordinatorDidFinish(self)
}
saveModalViewController.onButtonDismiss = dismissCallback
saveModalViewController.onDimmedAreaDismiss = dismissCallback
}
我想知道在以下情况下如何避免保留周期:
private func setupDismissCallbacks() {
// inner func
func dismiss() {
self.videoExporter?.cancel()
self.rootViewController.dismiss(animated: true, completion: nil)
self.delegate?.childCoordinatorDidFinish(self)
}
// first clousre
saveModalViewController.onButtonDismiss = { [weak self] in
// not really using `self` here
guard let self = self else { return }
dismiss()
}
// second clousre
saveModalViewController.onDimmedAreaDismiss = { [weak self] in
// not really using `self` here
guard let self = self else { return }
dismiss()
}
}
我有一个函数 setupDismissCallbacks
,它监听来自 saveModalViewController
自身 属性 的两个回调。 dismiss()
是 setupDismissCallbacks
中的一个内部函数,我用它来访问 self
值。
但是在闭包 onButtonDismiss
和 onDimmedAreaDismiss
中,我无法访问 self 来调用 dismiss
,而且我无法将 [weak self]
添加到 dismiss
函数,因为它是一个函数。
如何验证 dismiss
中的调用不会导致保留循环?
@Alexander 在评论中解释了这个问题:
Your inner function captures
self
. Your two closures capture that inner function (including the context it encloses over, which includesself
). Since your two closures are strongly referenced bysaveModalViewController
(which I assume is strongly referenced byself
), you have a retain cycle.
您可以通过不让 dismiss
捕获 self
来打破这个循环。将 SaveCoordinator
传递给 dismiss
:
private func setupDismissCallbacks() {
func dismiss(_ coordinator: SaveCoordinator) {
coordinator.videoExporter?.cancel()
coordinator(animated: true, completion: nil)
coordinator.delegate?.childCoordinatorDidFinish(coordinator)
}
// first clousre
saveModalViewController.onButtonDismiss = { [weak self] in
guard let self = self else { return }
dismiss(self)
}
// second clousre
saveModalViewController.onDimmedAreaDismiss = { [weak self] in
guard let self = self else { return }
dismiss(self)
}
}
只需将闭包分配给局部变量即可。那时,提取 dismiss
是没有意义的,所以直接内联它:
private func setupDismissCallbacks() {
let dismissCallback: () -> Void = { [weak self] in
guard let self = self else { return }
self.videoExporter?.cancel()
self.rootViewController.dismiss(animated: true, completion: nil)
self.delegate?.childCoordinatorDidFinish(self)
}
saveModalViewController.onButtonDismiss = dismissCallback
saveModalViewController.onDimmedAreaDismiss = dismissCallback
}