视图及其成员在演示后不会释放:
@main
struct ExampleApp: SwiftUI.App {
@State var show = false
var body: some Scene {
WindowGroup {
VStack {
Button("Present") { show = true }
Text("First")
.fullScreenCover(isPresented: $show) {
CheckSecond { show = false }
}
}
}
}
}
struct CheckSecond: View {
private let log = LogDeinit()
var action: () -> Void
var body: some View {
Text("Second")
Button("Back"){ action() }
}
}
class LogDeinit {
init(name: String) { print("init") }
deinit { print("deinit") }
}
来回显示“CheckSecond”会导致控制台中出现“init”,但不会出现“deinit”。内存映射显示“LogDeinit”对象由单个 SwiftUI 对象引用,无需任何额外连接。在 iOS 16 中可以正常工作 - 每次关闭时都会打印“deinit”。看来真的漏水了。
大多数人已经知道
@ObservedObject
是泄露,因为苹果在 WWDC 视频中这么说,例如这有一个严重的泄漏:
struct BadLeakView: View {
@ObserverdObject var log = LogDeinit() // bad leak
然而,你的示例是一个更严重的泄漏,因为你不仅在 View 结构中初始化了一个对象(SwiftUI 保留了
View
结构的许多副本,以便可以区分它们),而且你甚至没有将其包装在任何属性包装器中,例如这是一次非常严重的泄漏:
struct VeryBadLeakView: View {
let log = LogDeinit() // very bad leak!
您可以使用
@StateObject
修复此问题,但是您应该质疑是否需要一个对象,通常只有当您需要执行异步操作(例如组合管道)时才需要。由于我们现在有了 async/await,通常你甚至不再需要 @StateObject
,因为我们有 .task
,它就像一个状态对象,但作为一个更简单的视图修饰符。