情况:
我有一个视图控制器,它有一个表视图,从数组中获取数据。由于该数组的数据加载速度很慢,我的元素按需加载(在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;
}
问题:
这是预期的行为吗? 如果是的话,是否有办法破解它?如果没有,我做错了什么?
答案 0 :(得分:1)
这是一种意想不到的,实际上是无意的行为。我不知道你的自定义单元格的实现,但我无法想象这可能会导致这种行为。在我看来,你的-tableView实现没有问题:cellForRowAtIndexPath:本身。
我的怀疑是(i)在开始滚动你的tableview边界时以某种方式改变,或者(ii)Mac上安装的某些工具会干扰你的模拟器。所以我的建议如下:
(i)正如Dhruv Goel建议尝试硬编码行的高度。如果tableview的边界应该缩小,这可能会导致一些复杂性(行的高度越低,排队的行就越多)。但我无法想象为什么会发生这种情况的合理原因。
(ii)您是否通过模拟器专门调试您的应用程序?如果是,请查看以下链接:UITableViewCell cellForRowAtIndexPath calling large number of rows when first scrolling。像窗口管理那样的工具可能会干扰模拟器。
最后一点引出了另一个问题。您是否检查过UITableViewController的其他子类(在此特定项目中)是否出现此问题?
答案 1 :(得分:0)
是的,这是预期的行为。实际上,这是UITableView的主要功能之一。它只是在内存中保存当前必须在视图中显示的单元格。因此,当您滚动时,表视图会逐个将旧单元格出列,并将它们与新数据一起重用。因此,在您的情况下,最初可以看到5或6个单元格,并且您需要滚动并需要新单元格,即:
PlayerListCell* cell = [tableView dequeueReusableCellWithIdentifier:cellId];
如果可能,尝试重新使用单元格,如果没有,则使用以下命令创建新单元格:
if (!cell) {
cell = [[PlayerListCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];
}
围绕这个问题的方法是不要将单元格出列,并且每次都创建(alloc init)一个全新的单元格,但不建议这样做。
答案 2 :(得分:0)
这不是一个错误,它已被记录。
委托方法:
tableView:heightForHeaderInSection:
无论屏幕上是哪个单元格,都会调用tableview中的每个单元格。
正如文件中的讨论所说:
讨论
该方法允许委托指定具有不同高度的行。如果实现了此方法,则它返回的值将覆盖为给定行的UITableView的rowHeight属性指定的值。
使用tableView:heightForRowAtIndexPath:而不是rowHeight属性会对性能产生影响。每次显示表视图时,它会在每个行的委托上调用tableView:heightForRowAtIndexPath:这会导致表视图具有大量行(大约1000或更多)的显着性能问题