Uitableview 了解定制UITableCellView的创建-在MonoTouch中从NIB加载

Uitableview 了解定制UITableCellView的创建-在MonoTouch中从NIB加载,uitableview,xamarin.ios,nib,Uitableview,Xamarin.ios,Nib,我已经多次使用本教程: 但其中有一段代码我不太理解: cell = new MyCustomCell(); var views = NSBundle.MainBundle.LoadNib("MyCustomCell", cell, null); cell = Runtime.GetNSObject( views.ValueAt(0) ) as MyCustomCell; 我已经尝试过删除它——将LoadNib放在构造函数中——但是由于插座没有正确连接,所以出现了问题 有

我已经多次使用本教程:

但其中有一段代码我不太理解:

    cell = new MyCustomCell();
    var views = NSBundle.MainBundle.LoadNib("MyCustomCell", cell, null);
    cell = Runtime.GetNSObject( views.ValueAt(0) ) as MyCustomCell;
我已经尝试过删除它——将LoadNib放在构造函数中——但是由于插座没有正确连接,所以出现了问题

有人能解释一下这里发生了什么吗?为什么我不能在构造函数中加载这个Nib文件?为什么需要实际创建两个单元格实例?背景中到底发生了什么?代码可以改进吗

我有兴趣了解这一点,因为我经常这样做,我想让这个过程更干净

斯图尔特


如果有帮助的话,一个示例单元格是:

让我们一次看一件事情

LoadNib方法取消归档(并实例化)NIB的内容。第一个参数是NIB的名称,第二个参数是将要加载的NIB的所有者。也就是说,NIB的“文件所有者”占位符对象,在本例中,我认为它只是一个NSObject

LoadNib方法还返回对象的NSArray。这些对象是NIB的顶级对象,在本例中,NIB是您在NIB中创建的自定义单元

我想当您在构造函数中移动上述代码时,您会实现如下内容:

public MyCustomCell() : base()
{
    NSBundle.MainBundle.LoadNib("MyCustomCell", this, null);
}
如果您不这样做,并且您的实现是不同的,但是您仍然在构造函数中使用LoadNib,那么输出仍然无法保留。它们可以创建,但不会保留。它不是MonoTouch GC或任何东西,而是自动释放的本机出口。您可能会想,“但为什么我可以在UIViewController的构造函数中使用LoadNib,但仍然可以获得我的输出?”。这是正确的,您可以在UIViewController的构造函数中使用LoadNib,但有一个重要的区别:UIViewController是文件的所有者占位符对象。如果您尝试对一个不是文件所有者的控制器执行相同的操作,那么在保留输出时也会遇到同样的失败

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加载的更多信息:


我希望这能有所帮助。

我试图写一个完整的答案,但还是写不出来。这里面有很多东西。简而言之:您不需要从您的单元中连接到NIB中文件所有者的出口,您传递到LoadNib(..)的所有者应该声明出口。我目前正在写一篇关于NIB加载的文章,我相信这可以解释很多。在此之前,请检查我创建的示例项目:谢谢。我们期待着博客文章和学习。我很想向你介绍sib编辑器,但目前我发现整个过程有点混乱(可能也有问题)。Dimitri,回答得很好,刚刚发表了评论。我不确定设置
views=null
topLevelObjects=null
是否有用。如果它们是局部变量,您不必将它们设置为null——它们将毫无问题地得到GC'ed。我喜欢你的《你能咬吗?》一文,我自己也一直在想这些东西的内部结构。嗨,乔纳森。你是对的,只是我最近读了很多ObjC的东西。至于笔尖加载,我正在准备更多内容,请继续关注……;)是的,我在C#工作了这么久,我认为这是理所当然的。我不确定我是否能在Obj-C世界中成功。