表单和列表的 SwiftUI 内存泄漏

SwiftUI Memory Leak With Forms and Lists

我正在使用 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 ")
    }
}

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

您理解 deinit() 错误。当您关闭 View 时,并不一定意味着它会像您想象的那样调用 deinit()。如果您的 ViewModel 被销毁,它会如您所料调用 deinit()

为了演示这一点,这里有一个 Person class,名称为 属性,一个简单的初始化程序,以及一个打印消息的 printGreeting() 方法:

class Person {
    var name = "John Doe"

    init() {
        print("\(name) is alive!")
    }

    func printGreeting() {
        print("Hello, I'm \(name)")
    }
}

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

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

现在是去初始化器。这将在 Person 实例被 销毁 :

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

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

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

编辑

问题似乎已在 iOS 13.3.1

中解决