SwiftUI memory leak when referencing property from closure inside Form/NavigationView and swapping views

给你一囗甜甜゛ 提交于 2020-12-29 12:56:05

问题


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. 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.

Is there some way around this?

EDIT: Actually, when not not wrapping the button in NavigationView, there is no leak. As soon as I wrap the button, the leak appears. Wrapping in VStack is working out fine. But wrapping in Form produces the leak again. Seems like the same problem here: SwiftUI - Possible Memory Leak


回答1:


I found a solution: Make a weak viewModel in your action. It seems that Apple changed the behavior of closures. This means that the NavigationView is storing a strong reference to 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. Now, after dismissing the view, the viewModel is correctly deallocated.



来源:https://stackoverflow.com/questions/59303789/swiftui-memory-leak-when-referencing-property-from-closure-inside-form-navigatio

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!