表单和列表的 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
中解决
我正在使用 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
中解决