调用ReleaseDesignerOutlets对MonoTouch GC有什么影响吗?

时间:2012-10-24 13:22:40

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

我写的应用程序需要支持iOS5 +。最近,Apple已经过时ViewDidUnload,因为我们被告知在发布内存警告视图时没有显着的记忆增益。

在我的应用程序中,我有UIViewController来管理非常繁重的UIWebView 此视图控制器以模态方式呈现,因此通常会被创建和解除。

通过使用Instruments,我发现UIWebView占用的内存在其控制器被解除后不会立即被释放。

我认为控制器最终会被Mono GC收集,它会调用控制器上的Dispose,以及它的视图,它将部署UIWebView和释放底层本机对象。

我无法测试是否是这种情况:不幸的是,在呈现和解除控制器大约十次后,我收到内存警告,应用程序在下一秒崩溃。我不确定Mono GC是否有机会参加比赛。

所以我做的是在控制器被解雇后立即添加GC.Collect电话 我还必须在ReleaseDesignerOutlets中添加ViewDidDisappear

这似乎免费UIWebView

  

更新:我已经发现ReleaseDesignerOutlets中的ViewDidDisappear来电显然已经发布了网络视图,但GC呼叫没有任何好处。实际上, GC从未收集过我的控制器,因为按钮点击处理程序使整个控制器保持活动状态

现在,我觉得在某种货物记忆管理中完全迷失了。

  1. 在我的情况下强行收集垃圾是否合理?
  2. 为什么我必须致电ReleaseDesignerOutlets?当然,如果没有提到“死”控制器,它的观点也应该被视为有资格收集?
  3. 从Instruments heapshot diff看,它看起来像是从代码“保持”创建到控制器的视图。我必须处理它们吗?否定他们?
  4. 我是否需要在我刚刚解雇的控制器上手动呼叫Dispose
  5. 我是否需要在控制器的ReleaseDesignerOutlets方法中加入Dispose来电?
  6. 我是否需要在UIView上的自定义Dispose子类中取消对子视图的引用?

2 个答案:

答案 0 :(得分:4)

您应该在解除控制器时调用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。)< / p>

答案 1 :(得分:1)

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

正如您现在发现的那样,很容易遇到循环,当它们跨越MonoTouch / ObjectiveC边界时,GC无法确切地知道发生了什么并释放整个循环。

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