【问题标题】:UITableView reloadData doesnt reload the table but UITableView reloadSections workUITableView reloadData 不会重新加载表格,但 UITableView reloadSections 工作
【发布时间】:2016-03-21 18:50:27
【问题描述】:

我在父 UIView 中嵌入了一个 UITableView。我有一个 CustomUITableViewController 类设置为 tableview 的委托和数据源。 在某个后台操作之后,我得到了一个更新的对象数组,这些对象将显示在 tableview 中。

当我更新数据源数组并调用 tableview.reloadData 方法时,tableview 不会刷新。如果我滚动表格视图,它只会刷新。

但是,如果我按如下方式调用 API:

tableview.beginUpdates -> tableview.reloadSections -> tableview.endUpdates,

它完美运行并立即重新加载表格。 问题是,根据新数据,我必须添加一个新部分,或者从 tableview 中删除一个旧部分。

因此我无法使用 reloadSections API。

关于如何解决这个问题的任何想法?

代码:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *cellID = @"tempCell";
    CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
    if (cell == nil) {
        cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
    }
    [cell initializeWithModel:modelsToShow[indexPath.row]];
    return cell;
}
-(void) showModelsInList:(NSMutableArray*) models {
    [modelsToShow removeAllObjects];
    [modelsToShow addObjectsFromArray:models];
    [self setupDataForList];
    [self reloadTable];
}

-(void) reloadTable {
    [self.tableView beginUpdates];
    NSMutableIndexSet* index = [[NSMutableIndexSet alloc]init];
    [index addIndex:0];
    [self.tableView reloadSections:index withRowAnimation:UITableViewRowAnimationFade];
    [self.tableView endUpdates];
   //[self.tableView reloadData]
}

showModelsInList 方法是从主线程本身中的另一个类调用的。

【问题讨论】:

  • 你是从主线程(队列)调用reloadData吗?
  • 是的,我是。我直接尝试了 reloadData 以及 performSelectorOnMainThread API。他们两个都没有工作。
  • 请发布您的cellForRowAtIndex 实现以及您致电reloadData 的位置。
  • 我已更新问题以包含代码 sn-p。
  • 到目前为止您发布的内容看起来不错。请显示initializeWithModel。我正在寻找您对cellForRowAtIndexPath 中的单元格所做的更改。从排队的单元格添加/删除/重新排列视图并不总是立即更新,并且可能导致您描述的问题。相反,为每个布局使用不同的单元原型,并在cellForRowAtIndexPath 中相应地设置标识符。或者为了测试理论,只是为了测试,不要重复使用单元格(不要打电话dequeueReusableCellWithIdentifier),看看问题是否消失。

标签: ios objective-c uitableview


【解决方案1】:

我认为,从技术上讲,这是一个错误,但事实是,尽管没有记录,但在重用单元格时,您不应该在 cellForRowAtIndexPath 中重新创建子视图。

在界面生成器中设计时创建具有所有需要的子视图的单元格。在cellForRowAtIndexPath 中更改它们的位置、大小和其他属性是可以的。

如果您的单元格具有不同的子视图,则每个单元格“类型”应该是其自己的类。为每个单元创建一个具有不同标识符的不同原型单元类,并在使单元出列时简单地使用该标识符。这样,您在cellForRowAtIndexPath 中就有了正确的单元格类。

要从视图控制器引用其他属性(子视图),只需为每个单元类型(从 UITableViewCell 派生)创建类文件。将其分配给 IB 中的原型 UITableViewCell,将视图拖到 .h 文件中以创建出口,就像您为视图控制器所做的那样,然后将该类导入您的视图控制器中。

所以,你最终可能会得到这样的代码:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (whatever) {
       MyBasicCell *cell = [tableView dequeueReusableCellWithIdentifier:@"basicCell"];
       cell.specialLabel.Text = ...
       return cell;
    } else {
       MyOtherCell *cell = [tableView dequeueReusableCellWithIdentifier:@"otherCell"];
       cell.otherLabel.Text = ...
       return cell;
    }
}

【讨论】:

  • 我听从了您的建议,并使用 XIB 重新创建了一个全新单元格中的所有子视图。前一个是遗留代码,没有解决问题的方法。现在工作正常。谢谢!
【解决方案2】:

初始化表格视图单元格的现代方法是注册单元格类(或 nib,如果单元格在其自己的 nib 中定义)。 viewDidLoad 是这样做的好时机...

// if the cell is a prototype defined in the nib containing the table view, or if
// the cell is built in code in its init method
[self.tableView registerClass:[CustomCell self] forCellReuseIdentifier:@"tempCell"];

// or, if the cell is defined in its own nib
UINib *nib = [UINib nibWithNibName:@"your cell's nib name goes here" bundle:nil];
[_tableView registerNib:nib forCellReuseIdentifier:@"tempCell"];

在上述任何一种情况下,单元格都必须在 IB 或代码中初始化它的“tempCell”标识符。然后,在cellForRowAtIndexPath 中,使用方法将单元格出列...

CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:@"tempCell" forIndexPath:indexPath];

无需进一步检查即可查看if (cell == nil)。此版本的 dequeue 将正常工作(或崩溃,如果设置不正确)。

【讨论】:

  • 如果在 nib (storyboard) 中创建原型,则不需要注册类。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-18
  • 1970-01-01
  • 2013-03-04
  • 1970-01-01
相关资源
最近更新 更多