但是其中有一段我不太了解的代码:
cell = new MyCustomCell();
var views = NSBundle.MainBundle.LoadNib("MyCustomCell", cell, null);
cell = Runtime.GetNSObject( views.ValueAt(0) ) as MyCustomCell;
我试图删除它 - 将LoadNib放置在构造函数中 - 但是这些插座出错了,只是没有正确连接。
有人能说清楚这里发生了什么吗?为什么我不能只在构造函数中加载这个Nib文件?为什么有必要实际创建两个单元实例?背景中实际发生了什么?代码可以改进吗?
有兴趣了解这一点,因为我经常这样做,我很乐意让这个过程更加清洁
斯图尔特
如果有帮助,示例单元格为:https://github.com/slodge/MvvmCrossConference/blob/master/Cirrious.Conference.UI.Touch/Cells/SessionCell2.cs
答案 0 :(得分:5)
让我们一次看一下。
LoadNib方法取消归档(并实例化)NIB的内容。第一个参数是NIB的名称,第二个参数是将加载的NIB的所有者。也就是说,NIB的“文件所有者”占位符对象,在这种情况下,我认为它只是一个NSObject。
LoadNib方法还返回NSArray对象。这些对象是NIB的顶级对象,在本例中,它是您在NIB中创建的自定义单元格。
我想当你在构造函数中移动上面的代码时,你实现了这样的东西:
public MyCustomCell() : base()
{
NSBundle.MainBundle.LoadNib("MyCustomCell", this, null);
}
如果不这样做,并且您的实现不同,但您仍在构造函数中使用LoadNib,则仍无法保留插座。它们是可以创建的,但不会被保留。它不是MonoTouch GC的推出或任何东西,它是自动释放的本机插座。您可能想知道“但为什么我可以在UIViewController的构造函数中使用LoadNib并仍然可以获得我的插座?”。这是正确的,您可以在UIViewController的构造函数中使用LoadNib,但有一个重要的区别:UIViewController是您的File的Owner Placeholder对象。如果您尝试对不是文件所有者的控制器执行相同操作,则在保留插座时会出现同样的故障。
您在LoadNib方法中基本上需要的是顶级对象的返回数组。因此,为了使它在构造函数中工作,“正确”的方式是:
public MyCustomCell() : base()
{
NSArray arr = NSBundle.LoadNib("MyCustomCell", this, null);
this = Runtime.GetNSObject(arr.ValueAt(0)); // should retain everything,
//BUT: Compile error!
}
这与在构造函数之外加载NIB基本相同。但当然,我们不能做“这个=某事”。因此,总结一下LoadNib的创建:您的“MyCustomCell”是一个顶级对象,它通过LoadNib的返回值提供给我们,而不是通过将其作为所有者传递。
你正确注意到的下一件事是两个例子:我认为这也是错误的。看看上面的代码,并附上一些评论:
cell = new MyCustomCell(); // Created a new instance of MyCustomCell
var views = NSBundle.MainBundle.LoadNib("MyCustomCell", cell, null); // Assigned it as an owner
cell = Runtime.GetNSObject( views.ValueAt(0) ) as MyCustomCell; // What happens to the owner?
我认为这是一次内存泄漏。考虑以下因素:
// Not needed
//cell = new MyCustomCell();
var views = NSBundle.MainBundle.LoadNib("MyCustomCell", tableView, null); // Owner is now the tableView
cell = Runtime.GetNSObject( views.ValueAt(0) ) as MyCustomCell;
views = null; // Don't need it anymore
NIB的所有者现在是表格视图。表视图将由运行时处理(至少在大多数情况下)。
如果您仍想在MyCustomCell类中使用LoadNib来创建实例,只需创建一个静态方法:
// Inside MyCustomCell
public static MyCustomCell CreateCell(NSObject owner)
{
NSArray topLevelObjects = NSBundle.MainBundle.LoadNib("MyCustomCell", owner, null);
MyCustomCell customCell = Runtime.GetNSObject(topLevelObjects.ValueAt(0)) as MyCustomCell;
topLevelObjects = null;
return customCell;
}
有关NIB加载的更多信息:
Apple's Resource Programming Guide on NIB files
我希望这会有所帮助。