ios - 带有表单和列表的 SwiftUI 内存泄漏
问题描述
我正在开发简单的待办事项应用程序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 替换表单,则模型被取消。有针对这个的解决方法吗?
解决方案
你理解deinit()
错了。当您解雇 aView
时,它并不一定意味着它会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
推荐阅读
- javascript - 如何在 cypress 中单击表单按钮而不触发页面加载
- c# - 序列化继承自 ObservableObject 的模型
- javascript - 使用角度获取复选框的值
- mysql - MySQL - 如何在 IN 子句中使用具有逗号分隔字符串值的输入参数
- javascript - 如何按属性计算数组中的对象数?
- c++ - 即时将 coredump 转换为 minidump
- android - 如何将() LiveData 结果发送到现有的 LiveData 对象?
- ios - JSONSerialization 没有在服务器发送时序列化数据
- javascript - 如何在 Swiper 滑块的边缘设置幻灯片样式
- mysql - Node.js 中多个 Mysql 数据库的池连接