【问题标题】:SwiftUI Memory Leak With Forms and Lists带有表单和列表的 SwiftUI 内存泄漏
【发布时间】:2020-04-28 20:52:28
【问题描述】:

我正在使用SwiftUI 开发简单的待办事项应用程序。在我的测试中,我注意到我的视图模型从不调用 deinit 并导致内存使用量线性增加。

我用以下代码重现了相同的行为:

struct ContentView: View {
    @State private var isPresented = false

    var body: some View {
        Button("open") {
            self.isPresented = true
        }
        .sheet(isPresented: $isPresented) {
            SheetView()
        }
    }
}

struct SheetView: View {
    @ObservedObject var model: ViewModel

    init() {
        model = ViewModel()
    }

    var body: some View {
        Form {
            Toggle("Toggle Me", isOn: $model.isOn)
        }
    }
}

class ViewModel: ObservableObject {
    @Published var isOn = false

    deinit {
        print("ViewModel deinit ")
    }
}

当工作表被关闭时,模型对象永远不会取消初始化。如果我用 VStack 或 ScrollView 替换表单,则模型被取消。有解决办法吗?

【问题讨论】:

    标签: ios memory-leaks swiftui


    【解决方案1】:

    这是一个错误。只有对我有用的解决方法是使用 ScrollView。再说一次,ScrollView 有它自己的动画错误。

    编辑

    问题似乎已在 iOS 13.3.1 中得到解决

    【讨论】:

      【解决方案2】:

      您对deinit() 的理解是错误的。当您解雇 View 时,并不一定意味着它会像您想的那样调用 deinit()。如果您的 ViewModel 被销毁,但它会按照您的预期调用 deinit()

      为了演示这一点,这里有一个 Person 类,它有一个 name 属性、一个简单的初始化器和一个打印消息的 printGreeting() 方法:

      class Person {
          var name = "John Doe"
      
          init() {
              print("\(name) is alive!")
          }
      
          func printGreeting() {
              print("Hello, I'm \(name)")
          }
      }
      

      我们将在循环中创建Person 类的几个实例,因为每次循环循环都会创建一个新人,然后将其销毁:

      for _ in 1...3 {
          let person = Person()
          person.printGreeting()
      }
      

      现在是反初始化器。这将在Person 实例被销毁时调用:

      deinit {
          print("\(name) is no more!")
      }
      

      来源:https://www.hackingwithswift.com/sixty/8/6/deinitializers

      【讨论】:

      • 感谢您的回答。我知道 deinit() 是如何工作的。这里的问题是 ViewModel 应该在解雇后销毁。因为当 Form 替换为 VStack 时会发生这种情况。在当前状态下,如果我重新打开工作表 100 次,则创建了 100 个 ViewModel 实例但从未释放。
      • ViewModel 在 SheetView 中初始化,当 SheetView 被关闭时,应该不再有对 ViewModel 的引用。但看起来有,这是一种意外。例如,我在切换标签时也会遇到同样的情况。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-24
      • 2017-03-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-01
      相关资源
      最近更新 更多