不在 Xamarin 的 UIViewController 上调用 dealloc

Not calling dealloc on UIViewController in Xamarin

我有一个 UIViewController 写在绑定到我的 Xamarin 应用程序的本机库中。控制器有一个方法如下:

+ (instancetype)newInstance
{
    return [SharedData.sharedInstance.mainStoryboard instantiateViewControllerWithIdentifier:@"worksheetController"];
}

此方法绑定到我的 Xamarin 应用程序如下:

// @interface WorksheetTableViewController : UIViewController
[BaseType(typeof(UIViewController))]
interface WorksheetTableViewController
{
    // +(instancetype)newInstance;
    [Static]
    [Export("newInstance")]
    WorksheetTableViewController NewInstance();
}

现在,在我的 Xamarin 应用程序中,在 ViewDidLoad 的 UIViewController 子类中,我按如下方式调用该方法:

this.worksheetController = WorksheetTableViewController.NewInstance();

worksheetController 未在 UIViewController 的其他任何地方使用。当这个 UIViewController 被处理(通过弹出导航堆栈)时,WorksheetTableViewControllerdealloc 方法不会被调用。

但是,如果我将 ViewDidLoad 中的代码更改为如下:

this.worksheetController = (WorksheetTableViewController)SharedData.SharedInstance.MainStoryboard.InstantiateViewController("worksheetController");

UIViewController 被释放时,会调用 dealloc 方法。

对我来说,本地代码中的 newInstance 方法和直接在 Xamarin 中调用 InstantiateViewController 似乎没有任何区别。然而在前一种情况下 dealloc 没有被调用,而在后一种情况下一切都很好。

谁能解释一下为什么这两种情况下内存管理不同?

这是因为 ARC 将隐式保留本机 newInstance 方法 [1] 中的 return 值,而 Xamarin.iOS 不会隐式检测到该值。

您有两个选择:

  1. 将本机方法重命名为不以 newcopy 开头的名称(还有一些其他前缀,请参阅 [1] 了解完整信息列表),这样 ARC 就不会自动保留 return 值。

  2. [return: Release ()]添加到api定义中(这告诉Xamarin.iOSARC在做什么,Xamarin.iOS将添加一个额外的release调用):

    [Static]
    [Export("newInstance")]
    [return: Release ()]
    WorksheetTableViewController NewInstance();
    

[1] http://clang.llvm.org/docs/AutomaticReferenceCounting.html#method-families