如果UITableViewController在变量中引用嵌套类,它将进行垃圾回收
本文关键字:变量 UITableViewController 引用 嵌套 如果 | 更新日期: 2023-09-27 18:27:59
我遵循在MonoTouch(Xamarin.iOS)中创建UITableView的模式,将.Source属性设置为嵌套UITableViewSource类的新实例,如下所示。另一位开发人员让我注意到,这个UITableView类永远不会被垃圾收集,因为嵌套类通过嵌套类的构造函数中分配的_parentController属性引用了父类。人们相信,只要嵌套类持有这个引用,父类就无法被收集。
有人能确认这是否属实吗?以这种方式创建UITableView不是一种好的编程实践,因为垃圾收集将无法释放资源?(为了简洁起见,省略了一些方法和构造函数。
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;
}
}
}
它将被发布。
原因是"Source"属性在Objective-C中是一个弱属性,这意味着那里的赋值不会对对象调用retain,它只是保留对它的引用
只有当Objective-C调用保留在传递的对象上时,才会发生阻止GC发生的强循环。
以下示例显示了数据最终是如何发布的,您必须先向下钻取一系列时间,然后再向上钻取。
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;
}
}