从 Form/NavigationView 中的闭包引用属性并交换视图时,SwiftUI 内存泄漏 [英] SwiftUI memory leak when referencing property from closure inside Form/NavigationView and swapping views

查看:34
本文介绍了从 Form/NavigationView 中的闭包引用属性并交换视图时,SwiftUI 内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这样的事情:

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

按下按钮时,SomeView 关闭并呈现不同的视图.但是如果我检查内存图, SomeViewModel 仍然被分配,因为 self.viewModel.logOut() 在 Button 的动作闭包中被调用并且 Button 持有对 SomeViewModel.

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?

实际上,当没有将按钮包裹在 NavigationView 中时,没有泄漏.我一包住按钮,就会出现泄漏.包装在 VStack 中工作正常.但是包装在 Form 中再次产生泄漏.这里似乎是同样的问题:SwiftUI - 可能的内存泄漏

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

推荐答案

我找到了一个解决方案:在您的操作中创建一个弱 viewModel.苹果似乎改变了闭包的行为.这意味着 NavigationView 正在存储对 viewModel 的强引用.经过几天的调试,它终于对我有用了.

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

在最新的 Xcode 11.5 和 iOS 13.5 上测试.现在,在关闭视图后,viewModel 被正确释放.

Tested on the latest Xcode 11.5, with iOS 13.5. Now, after dismissing the view, the viewModel is correctly deallocated.

这篇关于从 Form/NavigationView 中的闭包引用属性并交换视图时,SwiftUI 内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆