簡體   English   中英

SwiftUI 在視圖層次結構中保留循環

[英]SwiftUI retain cycle in view hierarchy

我有以下具有保留周期的視圖層次結構,這是我可以重現問題的最簡單方法。 所有視圖模型和屬性都必須保留,因為它們在原始解決方案中是需要的:

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

如果我運行應用程序,點擊StartCooking ,然后點擊StopCooking並檢查 memory 圖,我仍然看到SubViewModel的實例,這意味着此代碼中存在泄漏。 如果我刪除:

  • NavigationView
  • 來自ContainerView的 VStack 或者
  • matchedGeometryEffect
  • tapGesture

保留周期已解決。 不幸的是我需要所有這些。 您能看出問題可能是什么以及如何解決嗎?

看起來像一個 SwiftUI 錯誤。 一種可能的解決方法(如果子視圖是一個或有限的集合)是使用視圖 model 工廠來提供實例。

這是一個視圖的示例:

struct SubView: View {

    @StateObject var viewModel = SubViewModel.shared  // single instance !!

    // .. other code
}

final class SubViewModel: ObservableObject {
    static var shared = SubViewModel()         // << this !!
}

我可以通過在 SubViewModel 中使每個屬性都是可選的並在SubViewModel消失時運行SubView來解決它,這使它們成為nil SubViewModel仍然停留在 memory,但不會占用那么多空間。

有趣的是,我什至嘗試將 viewmodel 設為可選,並在視圖消失時將其設為 nil,但它仍然停留在 memory。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM