为什么 RealityKit 内存在 deinit 调用后没有清除?

chi*_*hah 8 swift arkit realitykit

我无法从内存中释放我的 RealityKit ARView()。不幸的是,我知道 ARKit + SceneKit 也存在类似的问题,但解决方法并不能解决我的问题。

上述解决方案通过手动删除所有“可疑”内容来发挥作用。这正是我在更广泛的范围内所做的:

func closeCurrentView(completion: (() -> Void)? = nil, isScanAnotherFloor: Bool = false) {
    if backgroundRenderingID != UIBackgroundTaskIdentifier.invalid {
        let app = UIApplication.shared
        app.endBackgroundTask(self.backgroundRenderingID)
        self.backgroundRenderingID = UIBackgroundTaskIdentifier.invalid
    }
    self.arView?.session.pause()
    self.arView?.session.delegate = nil
    self.arView?.scene.anchors.removeAll()
    self.arView?.removeFromSuperview()
    self.arView?.window?.resignKey()
    self.arView = nil
}
Run Code Online (Sandbox Code Playgroud)

内存会上升到90MB到250MB,一旦deinit调用就会减少到175MB,不会清除所有内存。

另外在初始化时,我也设置了适当的选项。

arView?.renderOptions = [
    .disableMotionBlur,
    .disableDepthOfField,
    .disablePersonOcclusion,
    .disableGroundingShadows,
    .disableFaceOcclusions,
    .disableHDR
]
Run Code Online (Sandbox Code Playgroud)

但仍然没有运气。

在此输入图像描述

ARG*_*Geo 6

关于内存泄漏

\n

遗憾的是,RealityKit 2.0 / 1.0 开发人员无法ARView从堆内存中释放内存,因为 Apple 的实现质量很差。即使您像在 SwiftUI 中arView一样声明属性weak,该实例也会立即被释放,因此您无法使用它。然而,在 UIKit 中,声明arViewasweak没有任何效果。

\n

正如您所记得的,ARC 首先在 Objective-C 中引入,后来在 Swift 中实现。由于某种原因,ARView很可能没有实现weakunowned功能,也许是因为 RealityKit 是为 Swift 量身定制的,只有 \xe2\x80\x93@objc属性明确指出了这一点。看起来 ARView 弱引用没有被 ARC 跟踪(或者没有关联的Side Table)。

\n
@available(macOS 10.15, iOS 13.0, *)\n@objc open class ARView : ARViewBase { ... }\n
Run Code Online (Sandbox Code Playgroud)\n

如果您需要更多信息,请阅读这篇文章了解详细信息。

\n

(在 Xcode 14.3 中测试)

\n

  • 我认为不应该有解决方法。这是因为旧 ARView 的内存与您将来可能实例化的新 ARView 具有相似的属性。我想这只是为了让 ARView 在使用不同的或重复使用 ARView 执行重复的 AR 任务时加载得更快。我注意到,如果我在结束前一个 ARView 后重复实例化一个 ARView,内存使用量不会增加并保持相对相同。 (2认同)