我正在编写的应用程序需要支持 iOS5+。最近,Apple 淘汰了 ViewDidUnload,因为我们被告知在发布内存警告 View 时没有显着的内存增益。

在我的应用程序中,我有一个 UIViewController 来管理一个非常繁重的 UIWebView
这个 View Controller 以模态呈现,因此经常被创建和关闭。

通过使用 Instruments,我发现 UIWebView 占用的内存在其 Controller 被解除后并未立即释放。

我假设 Controller 最终会被 Mono GC 收集,并且它会在 Controller 及其 View 上调用 Dispose,这将处理 UIWebView 和释放底层 native 对象。

我无法测试是否是这种情况:不幸的是,在显示和关闭 Controller 大约十次后,我收到内存警告,应用程序在下一秒崩溃。我不确定 Mono GC 是否有机会运行。

所以我所做的是在 Controller 被解除后立即添加 GC.Collect 调用。
我还必须在 ReleaseDesignerOutlets 中添加 ViewDidDisappear

这似乎释放了 UIWebView



现在,我完全迷失在某种 Cargo 内存管理中。

  • 在我的情况下强制垃圾收集是否合理?
  • 为什么我必须调用 ReleaseDesignerOutlets ?当然,如果没有对“死” Controller 的引用,它的 View 也应该被视为有资格收集?
  • 从 Instruments 的 heapshot diff 来看,它看起来像是从代码“保持”到 Controller 创建的 View 。我必须处理它们吗?废掉他们?
  • 我是否需要在刚刚解雇的 Controller 上手动调用 Dispose
  • 我需要在 Controller 的 ReleaseDesignerOutlets 方法中包含 Dispose 调用吗?
  • 我是否需要在 UIView 的自定义 Dispose 子类中清除对 subview 的引用?
  • 最佳答案

    当它被关闭时,您应该只在 Controller 上调用 Dispose()

    所以像:

    private YourModalController modalController;
    
    //When your button is clicked
    partial void YourButtonClick() {
      modalController = new YourModalController();
      PresentViewController(modalController, true, delegate {
        modalController.Dispose();
        modalController = null;
      });
    }
    

    YourModalController 中,确保你有:
    public override void Dispose(bool disposing) {
      ReleaseDesignerOutlets();
      base.Dispose(disposing);
    }
    

    在这种情况下,您不必担心 ViewDidUnload,因为该 Controller 在解除时会被处理掉。

    在 iOS 6 之前:
  • ViewDidUnload 在应用
  • 的低内存警告中被调用
  • 在仍然在内存中但不在屏幕上的 Controller 上,例如在 UINavigationController
  • 中的堆栈
  • 在此事件中,您应该处理您拥有 C# 引用的所有 View ,并将它们设置为 null
  • for iOS 6 这不再发生

  • 同样,如果你有这个:
    private UIButton buttonIMadeFromCode;
    

    您应该检查 null,处理它,然后在 Dispose()ViewDidUnload() 中将其设置为 null(但如果您的目标低于 iOS 6,则只会与 ViewDidUnload 混淆)。

    关于ios - 调用 ReleaseDesignerOutlets 对 MonoTouch GC 有影响吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13050163/

    10-11 23:00
    查看更多