【问题标题】:Does calling ReleaseDesignerOutlets have any effect on MonoTouch GC?调用 ReleaseDesignerOutlets 对 MonoTouch GC 有影响吗?
【发布时间】:2012-10-24 13:22:40
【问题描述】:

我正在编写的应用程序需要支持 iOS5+。最近,Apple 废弃了ViewDidUnload,因为我们被告知在发布内存警告视图时不会显着增加内存。

在我的应用程序中,我有一个 UIViewController 来管理一个非常重的 UIWebView
此视图控制器以模态方式呈现,因此经常被创建和关闭。

通过使用 Instruments,我发现 UIWebView 占用的内存在其控制器关闭后并没有立即释放。

我假设控制器最终会被 Mono GC 收集,它会在控制器及其视图上调用 Dispose,这将释放 UIWebView 并释放底层原生对象。

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

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

这似乎释放了UIWebView

更新:我已经发现ViewDidDisappear 中的ReleaseDesignerOutlets 调用显然是在释放web 视图,但是GC 调用没有任何好处。事实上,GC 从未收集过我的控制器,因为按钮单击处理程序使整个控制器保持活动状态

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

  1. 在我的情况下强制垃圾收集是否合理?
  2. 为什么我必须打电话给ReleaseDesignerOutlets?当然,如果没有对“死”控制器的引用,那么它的视图也应该被认为有资格被收集?
  3. 从 Instruments 的 heapshot diff 来看,看起来从代码“等待”到控制器创建的视图也是如此。我必须处理它们吗?取消它们?
  4. 我是否需要在刚刚解散的控制器上手动调用Dispose
  5. 我需要在控制器的Dispose 方法中包含ReleaseDesignerOutlets 调用吗?
  6. 我是否需要在 Dispose 上的自定义 UIView 子类中取消对子视图的引用?

【问题讨论】:

  • 看来我现在有了一些进展。 navigationBar.TopItem.LeftBarButtonItem 包含指向自定义按钮的链接,该按钮包含指向我的控制器(事件处理程序)的链接。 GC 不能解决这个问题吗?

标签: ios memory-management xamarin.ios garbage-collection


【解决方案1】:

您应该在控制器关闭时调用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,因为此控制器在解除时被释放。

iOS 6 之前:

  • 在应用程序的内存不足警告中调用了ViewDidUnload
  • 在仍在内存中的控制器上,但不在屏幕上,例如在UINavigationController 中的堆栈下方
  • 在此事件中,您应该处置所有具有 C# 引用的视图并将它们设置为 null
  • 对于 iOS 6,这种情况不再发生

如果你有这个:

private UIButton buttonIMadeFromCode;

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

【讨论】:

  • 感谢您的回答。不过我仍然有疑问。让我们想象一下,我不想从代码中Dispose 控制器,并且当没有对它的引用时,我对 GC 调用 Dispose 感到满意。我是否认为,在这种情况下,在Dispose 中调用ReleaseDesignerOutlets 没有任何好处?因为,如果没有对视图控制器的引用并且它的视图不可见,它的子视图会被收集并释放吗?或者他们不会?
  • 重点是,当存在明确的处置途径且简单明了时,您不应该依赖GC。如果您手动处置,您的应用程序的整体性能会更好:更少的内存使用,更少的 GC 收集等。如果 GC 落后,这可能发生,iOS 可能会因为高内存使用而终止您的应用程序。
  • 是的,我明白你的意思,这就是我要走的路。我问是因为我想了解 MonoTouch GC 和 ObjC refcount 如何一起生活。我想我已经接近了,但我仍然不确定——如果我们从不明确地调用Dispose 并且控制器最终被收集,释放它的出口有什么好处吗?
  • 处置网点可以防止GC 以后不得不做这项工作。因此,如果您处置的是控制器而不是插座,GC 最终会为您处置插座。
【解决方案2】:

首先:MonoTouch 中的内存管理是一个非常复杂的话题,因为 MonoTouch(垃圾回收)必须与 ObjectiveC(引用计数)共存。

正如您现在发现的那样,很容易陷入循环,当这些越过 MonoTouch/ObjectiveC 边界时,GC 无法准确判断发生了什么并释放整个循环。

如果您对更深入的解释感兴趣,check this thread out

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-31
  • 2011-10-02
  • 2014-03-30
  • 2018-04-03
  • 1970-01-01
  • 2011-11-12
  • 2014-01-05
相关资源
最近更新 更多