如何清理 Xamarin.iOS 中的 UIViewController?

How to clean up a UIViewController in Xamarin.iOS?

假设我们有一个自定义的 UIViewContoller。

现在我们必须对 UIViewController 卸载进行一些清理。例如,如果我们在视图控制器中使用 UIWebView 作为子视图,建议将其委托设置为 null 并在卸载时调用 StopLoading() 方法。

一些消息来源说不建议重写 Dispose() 方法,因为它只涉及托管对象生命周期。

其他消息来源称不建议将 ViewDidDissappear() 用于这些目的,因为它可以被调用两次。

如何正确处理?

ViewDidDisappear()ViewWillDisappear()不会被多次调用;至少不是没有对 ViewDidAppear()ViewWillAppear() 的平衡调用。如果您看到对 disappear 方法的调用多于对 appear 方法的调用,那么您的代码中存在错误。如果你想确定,你的清理只发生一次(为了理智),但解决方案不是像这样简单的东西:

bool myCleanupIsDone = false;

public override void ViewDidDisappear()
{
  if(myCleanupIsDone)
  {
    return;
  }

  myCleanupIsDone = true;
  CleanUpWhateverNeedsToBeCleanedUp();
}

你几乎应该 never need to override Dispose() 除非你正在处理非托管资源。 Xamarin.iOS 在内部做了很多,但对于你的代码和你的情况来说它是不相关的。

通常您会在 ViewWillAppear() 中创建所需的对象并在消失方法中清理它们。这样你就不需要检查是否已经清理了一些东西。

ViewWillDisappearViewDidDisappear 实际上可以被调用多次,例如在 iPhone 上每次出现或推送新控制器时。但我认为它仍然是进行所有必要清理的正确位置。

一旦你的控制器第一次消失,Krumelur 的提议将以你的 UIWebView 的空委托结束——如果用户回来,它可能会崩溃。

因此,除了设置标志,您还可以检查您要清理的控制器是否正在弹出或关闭 – 如果是这种情况,您可以安全地完成所有工作。

这是我在我的一个项目中找到的一些代码(似乎我以前经历过这个;)):

public override void ViewDidDisappear(bool animated)
{
          if ((NavigationController == null && IsMovingFromParentViewController) ||
              (ParentViewController != null && ParentViewController.IsBeingDismissed))
          {
              CleanUpAfterDisappearing();
          }

          base.ViewDidDisappear(animated);
}

也许您可以在操作系统指示您的应用通过覆盖自定义视图控制器中的 DidReceiveMemoryWarning() 方法时清理资源:http://iosapi.xamarin.com/index.aspx?link=M%3AMonoTouch.UIKit.UIViewController.DidReceiveMemoryWarning