You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI父/子视图内存泄漏:是预期行为还是框架Bug?

问题分析:SwiftUI内存泄漏原因及结论

这不是SwiftUI的Bug,是代码中存在闭包循环引用导致的预期内存泄漏。

泄漏原因

  • 创建ChildView时传入的onHide闭包捕获了ContentView的overlayVisible状态(用于修改它),该闭包被ChildView持有。
  • ChildView的@StateObject标记的ChildViewStore是ObservableObject,SwiftUI会将其生命周期与ChildView绑定。
  • 闭包捕获了与ContentView相关的状态引用,ChildView又持有该闭包,形成循环引用链:ChildViewStore → ChildView → onHide闭包 → ContentView的状态引用,导致ChildViewStore在ChildView被移除后无法正常释放。

修复方案

方案1:打破闭包强捕获

修改ContentView中创建ChildView的代码,对状态绑定进行弱捕获:

ChildView(onHide: { [weak binding = $overlayVisible] in
    guard let binding = binding else { return }
    withAnimation {
        binding.wrappedValue = false
    }
})

方案2:改用Binding传递状态(更符合SwiftUI模式)

重构ChildView,用Binding替代闭包传递状态,从根源避免循环引用:

// 修改ChildView定义
struct ChildView: View {
    @Environment(\.presentationMode) var presentationMode
    @StateObject var store: ChildViewStore = ChildViewStore()
    @Binding var isVisible: Bool
    
    var body: some View {
        Color.gray
            .ignoresSafeArea(.all)
            .overlay{
                VStack {
                    Button("Dismiss") {
                        presentationMode.wrappedValue.dismiss()
                        withAnimation {
                            isVisible = false
                        }
                    }
                }
            }
    }
}

// 在ContentView中调用
ChildView(isVisible: $overlayVisible)

内容的提问来源于stack exchange,提问作者ramden

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 21:46:08