[英]SwiftUI retain cycle in view hierarchy
I'm having the following view hierarchy which has a retain cycle, that's the simplest I could make to reproduce the issue.我有以下具有保留周期的视图层次结构,这是我可以重现问题的最简单方法。 All viewmodels and properties has to stay as they are needed in the original solution:
所有视图模型和属性都必须保留,因为它们在原始解决方案中是需要的:
import SwiftUI
struct MainView: View {
@StateObject var viewModel = MainViewModel()
var body: some View {
NavigationView { [weak viewModel] in
VStack {
Button("StartCooking") {
viewModel?.show()
}
if viewModel?.isShowingContainerView == true {
ContainerView()
}
Button("StopCooking") {
viewModel?.hide()
}
}
}
.navigationViewStyle(.stack)
}
}
final class MainViewModel: ObservableObject {
@Published var isShowingContainerView = false
func show() {
isShowingContainerView = true
}
func hide() {
isShowingContainerView = false
}
}
struct ContainerView: View {
@Namespace var namespace
var body: some View {
VStack {
SubView(
namespace: namespace
)
}
}
}
struct SubView: View {
@StateObject var viewModel = SubViewModel()
var namespace: Namespace.ID
var body: some View {
Text("5 min")
.matchedGeometryEffect(id: UUID().uuidString, in: namespace)
.onTapGesture {
foo()
}
}
private func foo() {}
}
final class SubViewModel: ObservableObject {}
If I run the app, tap on StartCooking
, than on StopCooking
and check the memory graph, I still see an instance of SubViewModel
, which means that there is a leak in this code.如果我运行应用程序,点击
StartCooking
,然后点击StopCooking
并检查 memory 图,我仍然看到SubViewModel
的实例,这意味着此代码中存在泄漏。 If I remove:如果我删除:
NavigationView
OR NavigationView
或ContainerView
ORContainerView
的 VStack 或者matchedGeometryEffect
OR matchedGeometryEffect
或tapGesture
The retain cycle is resolved.保留周期已解决。 Unfortunately I need all these.
不幸的是我需要所有这些。 Can you see what the issue might be and how could it be solved?
您能看出问题可能是什么以及如何解决吗?
Looks like a SwiftUI bug.看起来像一个 SwiftUI 错误。 A possible workaround (if sub-view is one or limited set) is to use view model factory to provided instances.
一种可能的解决方法(如果子视图是一个或有限的集合)是使用视图 model 工厂来提供实例。
Here is an example for one view:这是一个视图的示例:
struct SubView: View {
@StateObject var viewModel = SubViewModel.shared // single instance !!
// .. other code
}
final class SubViewModel: ObservableObject {
static var shared = SubViewModel() // << this !!
}
I could kind of workaround it by making every property optional in the SubViewModel
and running a function when the SubView
s disappear, which makes them nil
.我可以通过在 SubViewModel 中使每个属性都是可选的并在
SubViewModel
消失时运行SubView
来解决它,这使它们成为nil
。 The SubViewModel
still stays in the memory, but will not take up that much space. SubViewModel
仍然停留在 memory,但不会占用那么多空间。
Interestingly I even tried to make the viewmodel optional, and make it nil when the view disappears, but it still stayed in the memory.有趣的是,我什至尝试将 viewmodel 设为可选,并在视图消失时将其设为 nil,但它仍然停留在 memory。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.