如果一个UITableViewController实例在变量中引用自己的嵌套类,它会收集吗? [英] Will a UITableViewController Garbage Collect if it instances a nested class referencing itself in a variable?

查看:104
本文介绍了如果一个UITableViewController实例在变量中引用自己的嵌套类,它会收集吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遵循在MonoTouch(Xamarin.iOS)中创建UITableView的模式,将.Source属性设置为嵌套UITableViewSource类的新实例,如下所示。另一位开发人员关注的问题是,由于嵌套类通过在嵌套类的构造函数中分配的_parentController属性嵌套类对父类的引用,因此此UITableView类永远不会收集垃圾。信仰是,只要嵌套类持有这个引用,父类将无法收集。

任何人都可以确认这是否为真,通过以这种方式创建UITableView并不是一种好的编程习惯,因为垃圾回收将无法释放资源? (一些方法和构造函数被简化了。

  public partial class MyViewController:UITableViewController 
{
public重写ViewDidLoad()
{
base.ViewDidLoad();
this.TableView.Source = new ViewSource(this);
}

public class ViewSource:UITableViewSource
{
MyViewController _parentController;
public ViewSource(MyViewController parentController)
{
_parentController = parentController;




解决方案

它将被释放。



原因是Source属性是Objective-C中的一个弱属性,这意味着那里的赋值没有在对象上调用retain,它只是保留对它。



只有当Objective-C调用保留在传递的对象上时,才会阻止GC发生的强周期。



以下示例显示了数据最终是如何发布的,您必须先钻取一堆,然后钻取。

  public class MyViewController:UITableViewController {
public override void ViewDidLoad()
{
base.ViewDidLoad();
this.TableView.Source = new ViewSource(this);

$ b $ public class ViewSource:UITableViewSource
{
public override int RowsInSection(UITableView tableview,int section)
{
return 100;


public override UITableViewCell GetCell(UITableView tableView,NSIndexPath indexPath)
{
return new UITableViewCell(UITableViewCellStyle.Default,foo);


public override void RowSelected(UITableView tableView,NSIndexPath indexPath)
{
var n = AppDelegate.window.RootViewController as UINavigationController;
n.PushViewController(new MyViewController(),true);
GC.Collect();
}
MyViewController _parentController;
public ViewSource(MyViewController parentController)
{
_parentController = parentController;
}
}
〜MyViewController()
{
Console.WriteLine(Disposing);


$ b $ [Register(AppDelegate)]
public partial class AppDelegate:UIApplicationDelegate
{
public static UIWindow window;
public override bool FinishedLaunching(UIApplication app,NSDictionary options)
{
window = new UIWindow(UIScreen.MainScreen.Bounds);

var myViewController = new MyViewController();
window.RootViewController = new UINavigationController(myViewController);
window.MakeKeyAndVisible();
返回true;
}
}


I follow a pattern of creating UITableView's in MonoTouch (Xamarin.iOS) by setting the .Source property to a new instance of a nested UITableViewSource class as shown below. The concern brought to my attention by another developer is that this UITableView class will never get garbage collected because of the nested class's reference to the parent class through the _parentController property assigned in the constructor of the nested class. The belief is that as long as the nested class is holding this reference the parent class will be unable to get collected.

Can anyone confirm if this is true and by creating UITableView's in this manner is not a good programming practice as garbage collection will be unable to free the resources? (some methods and constructors left out for conciseness.

public partial class MyViewController : UITableViewController
{
   public override ViewDidLoad()
   {
      base.ViewDidLoad();
      this.TableView.Source = new ViewSource(this);
   }

   public class ViewSource : UITableViewSource
   {
      MyViewController _parentController;
      public ViewSource(MyViewController parentController)
      {
         _parentController = parentController;
      }
   }
}

解决方案

It will be released.

The reason is that the "Source" property is a weak property in Objective-C, which means that the assignment there does not call retain on the object, it merely keeps a reference to it.

Strong cycles that would prevent GC from happening only happen if Objective-C calls retain on the passed object.

The following example shows how the data is eventually released, you have to first drill down a bunch of times, then drill back up.

public class MyViewController : UITableViewController {
    public override void ViewDidLoad()
    {
        base.ViewDidLoad();
        this.TableView.Source = new ViewSource(this);
    }

    public class ViewSource : UITableViewSource
    {
        public override int RowsInSection (UITableView tableview, int section)
        {
            return 100;
        }

        public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
        {
            return new UITableViewCell (UITableViewCellStyle.Default, "foo");
        }

        public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
        {
            var n = AppDelegate.window.RootViewController as UINavigationController;
            n.PushViewController (new MyViewController (), true);
            GC.Collect ();
        }
        MyViewController _parentController;
        public ViewSource(MyViewController parentController)
        {
            _parentController = parentController;
        }
    }
    ~MyViewController ()
    {
        Console.WriteLine ("Disposing");
    }
}

[Register ("AppDelegate")]
public partial class AppDelegate : UIApplicationDelegate
{
    public static UIWindow window;
    public override bool FinishedLaunching (UIApplication app, NSDictionary options)
    {
        window = new UIWindow (UIScreen.MainScreen.Bounds);

        var myViewController = new MyViewController ();
        window.RootViewController = new UINavigationController (myViewController);
        window.MakeKeyAndVisible ();
        return true;
    }
}

这篇关于如果一个UITableViewController实例在变量中引用自己的嵌套类,它会收集吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆