0

情况:

我有一个视图控制器,它有一个表视图,它从数组中获取数据。由于该数组的数据加载速度很慢,我让元素按需加载(在 tableView:cellForRowAtIndexPath: 处触发)。

问题:

在开始时(即在视图加载后)它只加载可见单元格(前 6 个)。但是,当您尝试滚动时,它会立即加载其他所有人!(通过负载断点测试,显然 [UITableView _createPreparedCellForGlobalRow:withIndexPath:] 为每一行调用)

编码:

PlayerListDataModel.m

@implementation PlayerListDataModel
(...)
-(NSString *)nombre {
    if (!self.loaded) [self load];
    return _nombre;
}
-(void)load {
    NSLog(@"Loading %d", self.sqlId);
    [OMNIGAME loadListCell:self];
    self.loaded = YES;
}
@end

PlayerListViewController.m

@implementation PlayerListViewController

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; }

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.jugadores.count;
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString* cellId = @"PlayerListCell";
    PlayerListCell* cell = [tableView dequeueReusableCellWithIdentifier:cellId];
    if (!cell) {
        cell = [[PlayerListCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];
    }
    PlayerListDataModel* data =[self.jugadores objectAtIndex:indexPath.row];
    cell.dem = data.bestDem;
    cell.nombre = data.nombre;
    cell.apellido = data.apellido;
    cell.escudo = data.escudo;
    cell.equipo = data.equipo;
    cell.age = data.edad;
    cell.bandera = data.bandera;
    cell.price = data.price;
    cell.energia = data.energy;
    cell.valor = data.valor;

    return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    return tableView.bounds.size.height/7;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return tableView.bounds.size.height/7;
}
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    if (!self.search) {
        self.search = [[PlayerSearchView alloc] init];
        self.search.search.delegate = self;
    }
    return self.search;
}

问题:

这是预期的行为吗?如果是,是否有任何方法可以破解它?如果没有,我做错了什么?

4

3 回答 3

1

这是出乎意料且确实是意外的行为。我不知道您的自定义单元格的实现,但我无法想象这可能会导致这种行为。在我看来,您的 -tableView:cellForRowAtIndexPath: 实现本身没有任何问题。

我的怀疑是(i)在开始滚动表格视图的边界时会以某种方式发生变化,或者(ii)Mac上安装的某些工具会干扰您的模拟器。所以我的建议如下:

(i) 正如 Dhruv Goel 建议的那样,尝试硬编码行的高度。如果您的 tableview 的边界应该缩小,这可能会导致一些复杂性(行的高度越低,必须排队的行越多)。但我无法想象为什么会发生这种情况的适当理由。

(ii) 您是否只通过模拟器调试您的应用程序?如果是这样,请查看此链接:UITableViewCell cellForRowAtIndexPath 在第一次滚动时调用大量行。像那些用于窗口管理的工具可能会干扰模拟器。

最后一点让我想到另一个问题。您是否检查过此问题是否也出现在 UITableViewController 的其他子类中(在此特定项目中)?

于 2013-06-18T22:40:49.590 回答
0

是的,这是预期的行为。事实上,这是 UITableView 的主要功能之一。它只是将当前必须显示的单元格保存在内存中。因此,当您滚动时,表格视图会将旧单元格逐个出列,并将它们与新数据一起重用。因此,在您的情况下,最初有 5 或 6 个单元格在视图中,并且您滚动并需要新单元格,该行:

PlayerListCell* cell = [tableView dequeueReusableCellWithIdentifier:cellId];

如果可能,尝试重新使用单元格,如果没有,则使用以下命令创建新单元格:

if (!cell) {
cell = [[PlayerListCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];
}

解决此问题的方法是不使单元格出列,并且每次都创建(alloc init)一个全新的单元格,但不建议这样做。

于 2013-06-18T20:28:59.347 回答
0

这不是错误,它已记录在案。

委托方法:

tableView:heightForHeaderInSection:

为表格视图中的每个单元格调用,无论屏幕上有哪些单元格。

正如文档中的讨论所说:

讨论

该方法允许委托指定具有不同高度的行。如果实现了此方法,则它返回的值将覆盖为给定行的 UITableView 的 rowHeight 属性指定的值。

使用 tableView:heightForRowAtIndexPath: 代替 rowHeight 属性会影响性能。每次显示表视图时,它都会在委托上为其每一行调用 tableView:heightForRowAtIndexPath:,这可能会导致具有大量行(大约 1000 或更多)的表视图出现严重的性能问题

于 2013-08-28T15:18:26.923 回答