我写的应用程序需要支持iOS5 +。最近,Apple已经过时ViewDidUnload
,因为我们被告知在发布内存警告视图时没有显着的记忆增益。
在我的应用程序中,我有UIViewController
来管理非常繁重的UIWebView
此视图控制器以模态方式呈现,因此通常会被创建和解除。
通过使用Instruments,我发现UIWebView
占用的内存在其控制器被解除后不会立即被释放。
我认为控制器最终会被Mono GC收集,它会调用控制器上的Dispose
,以及它的视图,它将部署UIWebView
和释放底层本机对象。
我无法测试是否是这种情况:不幸的是,在呈现和解除控制器大约十次后,我收到内存警告,应用程序在下一秒崩溃。我不确定Mono GC是否有机会参加比赛。
所以我做的是在控制器被解雇后立即添加GC.Collect
电话
我还必须在ReleaseDesignerOutlets
中添加ViewDidDisappear
。
这似乎免费UIWebView
。
更新:我已经发现
ReleaseDesignerOutlets
中的ViewDidDisappear
来电显然已经发布了网络视图,但GC呼叫没有任何好处。实际上, GC从未收集过我的控制器,因为按钮点击处理程序使整个控制器保持活动状态。
现在,我觉得在某种货物记忆管理中完全迷失了。
ReleaseDesignerOutlets
?当然,如果没有提到“死”控制器,它的观点也应该被视为有资格收集?Dispose
?ReleaseDesignerOutlets
方法中加入Dispose
来电? UIView
上的自定义Dispose
子类中取消对子视图的引用?答案 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
同样,如果你有这个:
private UIButton buttonIMadeFromCode;
你应该检查null,处理它,并在Dispose()
和ViewDidUnload()
中将其设置为null(但如果你的目标是低于iOS 6,则只会混淆ViewDidUnload
。)< / p>
答案 1 :(得分:1)
首先:MonoTouch中的内存管理是一个非常复杂的主题,因为MonoTouch(垃圾收集)必须与ObjectiveC(引用计数)共存。
正如您现在发现的那样,很容易遇到循环,当它们跨越MonoTouch / ObjectiveC边界时,GC无法确切地知道发生了什么并释放整个循环。
如果您对更深入的解释感兴趣,check this thread out。