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

RealityKit调用deinit后内存未完全释放,ARView实例无法彻底释放内存的问题求助

为什么RealityKit的ARView实例在调用deinit后内存无法完全释放?

我之前也踩过RealityKit内存释放的坑,结合实践经验和对框架的理解,来帮你拆解可能的原因和解决思路:

可能的原因分析

1. ARSession的隐式强引用残留

你已经做了暂停session、置空delegate的操作,但RealityKit的ARView和ARSession之间存在一些框架内部的隐式强引用——比如session可能还持有摄像头帧缓存、空间映射数据的引用,这些不会仅仅通过pause()就立刻释放。常规的清理操作可能没触及到这些深层关联。

2. 场景资源的递归引用未清理

你移除了所有scene anchors,但每个anchor下的实体(比如ModelEntity)可能还持有材质、模型文件等资源的强引用,甚至这些资源可能被RealityKit的全局资源缓存池持有,手动移除anchors并不会自动递归清理这些子实体的资源。

3. 系统级AR资源缓存

iOS系统本身会对AR相关的资源做复用缓存,比如ARKit的跟踪数据、摄像头纹理缓存等。这些缓存不会在你关闭ARView后立刻被回收,而是留在内存中供后续AR会话快速启动,这部分内存占用是系统层面的,不属于内存泄漏。

4. 循环引用未被发现

如果你的ViewController或其他对象通过闭包、自定义delegate持有了ARView的强引用(比如闭包没加weak self),会导致ARView无法被正常deinit,内存自然无法释放。

针对性的改进方案

1. 更彻底的ARSession清理

在暂停session后,尝试用空配置重置session,强制清理内部状态:

self.arView?.session.pause()
// 用空配置重置跟踪,移除所有现有锚点
let emptyConfig = ARConfiguration()
self.arView?.session.run(emptyConfig, options: [.resetTracking, .removeExistingAnchors])
self.arView?.session.pause()
self.arView?.session.delegate = nil

2. 递归清理所有实体资源

遍历所有锚点和子实体,手动清理模型、材质等资源,断开所有引用链:

func clearEntities(_ entity: Entity) {
    for child in entity.children {
        clearEntities(child)
        child.removeFromParent()
        // 清理ModelEntity的模型和材质
        if let modelEntity = child as? ModelEntity {
            modelEntity.model = nil
            modelEntity.materials.removeAll()
        }
        // 移除AnchorEntity的场景关联
        if let anchorEntity = child as? AnchorEntity {
            anchorEntity.removeFromScene()
        }
    }
}

// 遍历所有锚点并清理
self.arView?.scene.anchors.forEach { anchor in
    clearEntities(anchor)
    anchor.removeFromScene()
}
self.arView?.scene.anchors.removeAll()

3. 断开视图的所有外部引用

除了removeFromSuperview(),还要置空window引用,确保没有其他视图层级持有ARView:

self.arView?.removeFromSuperview()
self.arView?.window = nil
self.arView = nil

4. 排查循环引用

用Xcode的Memory Graph Debugger(调试栏中的内存图标)查看内存中的对象,找到哪些对象还持有ARView的引用——重点检查闭包、自定义代理是否使用了weak或unowned修饰。

5. 区分系统缓存和内存泄漏

如果清理后内存维持在175MB不再上涨,尝试再次创建并关闭ARView:

  • 如果第二次关闭后内存没有继续增加,说明第一次的残留是系统缓存,属于正常现象,iOS会在内存紧张时自动回收。
  • 如果内存持续上涨,那大概率是存在未被清理的强引用,需要进一步排查。

完整改进后的清理函数

func closeCurrentView(completion: (() -> Void)? = nil, isScanAnotherFloor: Bool = false) {
    // 结束后台任务
    if backgroundRenderingID != UIBackgroundTaskIdentifier.invalid {
        UIApplication.shared.endBackgroundTask(self.backgroundRenderingID)
        self.backgroundRenderingID = UIBackgroundTaskIdentifier.invalid
    }
    
    // 彻底清理ARSession
    self.arView?.session.pause()
    let emptyConfig = ARConfiguration()
    self.arView?.session.run(emptyConfig, options: [.resetTracking, .removeExistingAnchors])
    self.arView?.session.pause()
    self.arView?.session.delegate = nil
    
    // 递归清理实体资源
    func clearEntities(_ entity: Entity) {
        for child in entity.children {
            clearEntities(child)
            child.removeFromParent()
            if let modelEntity = child as? ModelEntity {
                modelEntity.model = nil
                modelEntity.materials.removeAll()
            }
            if let anchorEntity = child as? AnchorEntity {
                anchorEntity.removeFromScene()
            }
        }
    }
    self.arView?.scene.anchors.forEach { anchor in
        clearEntities(anchor)
        anchor.removeFromScene()
    }
    self.arView?.scene.anchors.removeAll()
    
    // 移除视图并断开引用
    self.arView?.removeFromSuperview()
    self.arView?.window = nil
    self.arView = nil
    
    // 触发自动释放池清理(调试用,Release环境可省略)
    autoreleasepool {}
    
    completion?()
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 17:17:29