首页 > 解决方案 > Xamarin iOS UITableView 在初始设置时为所有单元调用委托方法,而不仅仅是可见的

问题描述

我有一个UITableView自定义单元格。这个 TableView 在一个 View Controller 中,占据了 View 的全部维度。每个RowHeight单元格的 设置为 TableView 的高度,因此每个单元格占据全屏(减去导航栏)。这是该设置的屏幕截图。Red是我的自定义单元格;向下滑动会翻页到下一个,它的颜色不同:

UITableView 单元格

当 TableView 第一次在屏幕上可见时,我将模型(颜色集合)传递给一个Setup方法,然后该方法设置Delegates. 在此初始设置期间,尽管一次只有一个单元格可见,但会为每个GetCell单元格调用委托的方法。然后这会触发类的和委托方法。UITableViewDataSourceWillDisplayCellDisplayingEndedUITableViewDelegate

我的印象是UITableView只会根据需要创建每个单元格的实例(当变得可见时),但它似乎正在为加载的每个单元格创建一个实例,而不管可见性如何。

我创建了一个精简的样本以共享,该表总共有 6 条记录。然后我在上述每个委托方法的开头添加了一个日志,这是设置 TableView 时的输出:

[0:] GetCell called. Row 0
[0:] WillDisplayCell called. Row 0, RowHeight 672
[0:] GetCell called. Row 1
[0:] WillDisplayCell called. Row 1, RowHeight 672
[0:] GetCell called. Row 2
[0:] WillDisplayCell called. Row 2, RowHeight 672
[0:] GetCell called. Row 3
[0:] WillDisplayCell called. Row 3, RowHeight 672
[0:] GetCell called. Row 4
[0:] WillDisplayCell called. Row 4, RowHeight 672
[0:] GetCell called. Row 5
[0:] WillDisplayCell called. Row 5, RowHeight 672
[0:] CellDisplayingEnded called. Row 1, RowHeight: 672
[0:] CellDisplayingEnded called. Row 2, RowHeight: 672
[0:] CellDisplayingEnded called. Row 3, RowHeight: 672
[0:] CellDisplayingEnded called. Row 4, RowHeight: 672
[0:] CellDisplayingEnded called. Row 5, RowHeight: 672

如前所述,一次只能在屏幕上看到一个单元格。为什么最初创建所有 6 个单元格?

示例代码

public class SampleCell : UITableViewCell {
    public void Setup(UIColor color) {
        BackgroundColor = color;
    }
}

public class SampleTableViewDataSourceDelegate : UITableViewDataSource {
    public SampleTableViewDataSourceDelegate(UIColor[] model) {
        this.model = model;
    }

    private readonly UIColor[] model;

    public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath) {
        Debug.WriteLine($"GetCell called. Row {indexPath.Row}");
        var reuseIdentifier = "SampleCell";

        var cell = tableView.DequeueReusableCell(reuseIdentifier) as SampleCell;

        cell = (cell ?? (cell = new SampleCell()));

        cell.Setup(model[indexPath.Row]);

        return cell;
    }

    public override nint NumberOfSections(UITableView tableView) {
        return 1;
    }

    public override nint RowsInSection(UITableView tableView, nint section) {
        return model.Length;
    }
}

public class SampleTableViewDelegate : UITableViewDelegate {
    public SampleTableViewDelegate(UIColor[] model) {
        this.model = model;
    }

    private readonly UIColor[] model;

    public override void WillDisplay(UITableView tableView, UITableViewCell cell, NSIndexPath indexPath) {
        Debug.WriteLine($"WillDisplayCell called. Row {indexPath.Row}, RowHeight {tableView.RowHeight}");
    }

    public override void CellDisplayingEnded(UITableView tableView, UITableViewCell cell, NSIndexPath indexPath) {
        Debug.WriteLine($"CellDisplayingEnded called. Row {indexPath.Row}, RowHeight: {tableView.RowHeight}");
    }
}

public partial class SampleTableView : TableViewBase {
    public SampleTableView(IntPtr handle) : base(handle) {
        PagingEnabled = true;
    }

    private UIColor[] model;

    public void Setup(UIColor[] model) {
        this.model = model;

        Delegate = new SampleTableViewDelegate(model);
        DataSource = new SampleTableViewDataSourceDelegate(model);
    }
}

然后,在 my 中ViewController,我按如下方式传递模型:

public override void ViewDidLoad() {
    base.ViewDidLoad();

    var model = new UIColor[] {
        UIColor.Green,
        UIColor.Red,
        UIColor.Magenta,
        UIColor.Cyan,
        UIColor.Blue,
        UIColor.Purple
    };

    SampleTableView.RowHeight = SampleTableView.Frame.Height;
    SampleTableView.Setup(model);
}

标签: c#iosuitableviewxamarinxamarin.ios

解决方案


哦,lawd,EstimatedRowHeight也需要设置。

SampleTableView.EstimatedRowHeight = SampleTableView.Frame.Height;

这解决了我的问题。现在GetCell只在加载时调用一次,因为一次只有一个可见单元格。

文档(苹果,但同样适用于 xamarin): https ://developer.apple.com/documentation/uikit/uitableview/1614925-estimatedrowheight


推荐阅读