[英]SwiftUI memory leak when referencing property from closure inside Form/NavigationView and swapping views
I have something like this:我有这样的事情:
struct SomeView: View {
@ObservedObject var viewModel: SomeViewModel
var body: some View {
NavigationView { // <- culprit
Button(action: { self.viewModel.logOut() }) { Text("X").frame(width: 40, height: 40) }
}
}
class SomeViewModel: ObservableObject {
func logOut() {
// changes global state, based on which the views are swapped, so `SomeView` is removed and replaced by a different one
}
}
When the button is pressed, SomeView
is closed and a different view is presented.按下按钮时, SomeView
关闭并呈现不同的视图。 But if I check the memory graph, SomeViewModel
is still allocated because self.viewModel.logOut()
is called in the Button's action closure and Button is holding the reference to SomeViewModel
.但是如果我检查内存图, SomeViewModel
仍然被分配,因为在 Button 的动作闭包中调用了 self.viewModel.logOut self.viewModel.logOut()
并且 Button 持有对SomeViewModel
的引用。
Is there some way around this?有什么办法解决这个问题吗?
EDIT: Actually, when not not wrapping the button in NavigationView
, there is no leak.编辑:实际上,当不在NavigationView
中包装按钮时,没有泄漏。 As soon as I wrap the button, the leak appears.我一包裹按钮,就会出现泄漏。 Wrapping in VStack
is working out fine.在VStack
中包装效果很好。 But wrapping in Form
produces the leak again.但是用Form
包装会再次产生泄漏。 Seems like the same problem here: SwiftUI - Possible Memory Leak在这里似乎是同样的问题: SwiftUI - Possible Memory Leak
I found a solution: Make a weak viewModel
in your action.我找到了一个解决方案:在您的操作中创建一个弱viewModel
。 It seems that Apple changed the behavior of closures. Apple 似乎改变了闭包的行为。 This means that the NavigationView
is storing a strong reference to viewModel.这意味着NavigationView
正在存储对 viewModel 的强引用。 After a couple days of debugging, it finally worked for me.经过几天的调试,它终于对我有用了。
Button(action: {
[weak viewModel] in viewModel?.dismissButtonPressed.send(())
}) {
Image("crossmark")
.padding()
.foregroundColor(Color.white)
}
}
In your problem, this will be solved like this:在您的问题中,这将像这样解决:
NavigationView {
[weak viewModel] in Button(action: { viewModel?.logOut() }) {
Text("X").frame(width: 40, height: 40)
}
}
Tested on the latest Xcode 11.5, with iOS 13.5.在最新的 Xcode 11.5 和 iOS 13.5 上进行了测试。 Now, after dismissing the view, the viewModel
is correctly deallocated.现在,在关闭视图后, viewModel
被正确释放。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.