【问题标题】:Not Enough Cell to Use in UITableView没有足够的单元格在 UITableView 中使用
【发布时间】:2015-03-26 05:31:39
【问题描述】:

我在 Storyboard 中创建了一个 UITableView,它是动态单元格。问题是当没有足够的单元格可以重复使用时,它会随机清空我的一些单元格。我认为这是合乎逻辑的,但我想解决这个问题。

我举个例子: 我有一个 UITableView 能够在一个视图中生成 10 个单元格。但是现在,我只想显示 10 个单元格中的 8 个单元格。当我只有一个部分时,它没有问题。超过 1 个部分,它总是会清空 2 个单元格并显示 8 个单元格,但它应该显示 10 个单元格。

谁能帮我解决这个问题?谢谢。

已更新源代码

#pragma mark - List View
#pragma mark - Table View Delegate
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
   return 2;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:   (NSInteger)section {
   // Number of rows is the number of time zones in the region for the          specified section.
  return self.listCollection.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

   UITableViewCell *cell = [tableView  dequeueReusableCellWithIdentifier:@"ListCell" forIndexPath:indexPath];

   for (id object in cell.contentView.subviews) {
       [object removeFromSuperview];
   }

   [cell.contentView addSubview:[self.listCollection   objectAtIndex:indexPath.row]];

   return cell;

}

self.listCollection 有一个 UIView 对象数组。

已更新图片:

  1. Image 1
  2. Image 2

【问题讨论】:

  • 您“想在不滚动视图的情况下显示 10 个单元格中的 8 个”?
  • 实际上没有。我的表格视图可以显示 8 个单元格而无需滚动。我的意思是当有多个部分时,有 2 个空单元格,但它假设显示 10 个单元格,这会导致错误。
  • 发布您如何填充单元格的代码。
  • 当您的数据源委托返回 1 时,您为什么会得到 2 个部分?
  • 不知道是否与问题有关。在这些行中 for (id object in cell.contentView.subviews) { [object removeFromSuperview]; } [cell.contentView addSubview:[self.listCollection objectAtIndex:indexPath.row]];为什么不创建一个包含这些子视图的自定义单元格?

标签: ios objective-c iphone uitableview


【解决方案1】:

发生这种情况是因为您使用了 2 个部分,但没有分别指定每个部分的内容。要理解这一点,我们需要查看 Apple Documentation 中对 addSubview: 方法的描述

此方法建立对视图的强引用,并将其下一个响应者设置为接收者,即其新的超级视图。

视图只能有一个超级视图。如果视图已经有一个超级视图并且该视图不是接收者,则此方法会在将接收者设为新的超级视图之前删除之前的超级视图

仔细查看第二段中的粗体部分。由于您使用来自listCollection 的相同视图对象来填充这两个部分,因此最新创建的单元格将成为此视图对象的superview,而前一个单元格将被排除在外,只有平面contentView。您可以通过为单元格contentView 分配一些默认颜色来获得真实的感觉。您的空白单元格将显示完整内容的颜色,而其他单元格将显示 view

cell.contentView.backgroundColor = [UIColor greenColor];

解决方案
我将建议对这两个部分使用 2 个不同的数据源,如下所述。

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:   (NSInteger)section {
   // Number of rows is the number of time zones in the region for the          specified section.  
   if(section==0)
      return self.listCollection.count; 
   else   
      return <row count for section 1>  
 }

您需要为每个部分修改cellForRowAtIndexPath: 代码。

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

   UITableViewCell *cell = [tableView  dequeueReusableCellWithIdentifier:@"ListCell" forIndexPath:indexPath];

   for (id object in cell.contentView.subviews) {
       [object removeFromSuperview];
   }
   if(section==0)
      [cell.contentView addSubview:[self.listCollection   objectAtIndex:indexPath.row]];
   else
      [cell.contentView addSubview:[<second array of views>   objectAtIndex:indexPath.row]];

   return cell;
}

但是,如果您必须使用相同的数组,那么您可以使用这种技术。感谢Rishi
最后但同样重要的是,您应该使用 Michal Zygar 在他的帖子中建议的自定义 UITableViewCell 类。

UIView *tempView = [self.listCollection objectAtIndex:indexPath.row];
NSData *tempArchiveView = [NSKeyedArchiver archivedDataWithRootObject:tempView];
UIView *viewOfSelf = [NSKeyedUnarchiver unarchiveObjectWithData:tempArchiveView];
[cell.contentView addSubview:viewOfSelf];

【讨论】:

  • 哇,这真的很酷。非常感谢,它解决了问题。你能解释一下 NSData 是如何工作的吗?
  • archivedDataWithRootObject 将根对象(即tempView)转换为二进制数据,并在取消归档此数据时从该数据创建一个对象。此过程维护对象的数据类型,但将返回UIView 的新对象。详情请查看Documentation
  • 很好的解释,非常感谢。你知道任何可以帮助 iOS 开发者提高技能的网站吗?
  • @tan- Ray WenderlichBig Nerd 有很多初学者教程。
【解决方案2】:

您以错误的方式使用 UITableView。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

   UITableViewCell *cell = [tableView  dequeueReusableCellWithIdentifier:@"ListCell" forIndexPath:indexPath];

   for (id object in cell.contentView.subviews) {
       [object removeFromSuperview];
   }

   [cell.contentView addSubview:[self.listCollection   objectAtIndex:indexPath.row]];

   return cell;

}

这是非常不恰当的。您的 listCollection 应该包含模型数据。在- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 中,您应该使用此数据配置单元格。

所以你应该继承 UITableViewCell 例如

@interface ApartmentCell:UITableViewCell
@property (weak, nonatomic) UILabel* floor;
@property (weak, nonatomic) UILabel* unit;
@property (weak, nonatomic) UILabel* type;
@property (weak, nonatomic) UILabel* area;
@property (weak, nonatomic) UILabel* price;
@end

然后

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

  ApartmentCell *cell = [tableView  dequeueReusableCellWithIdentifier:@"ListCell" forIndexPath:indexPath];
  Apartment* apartment=self.listCollection[indexPath.row];

  cell.unit.text=apartment.unit;
   //and so on with other fields
  return cell;
}

【讨论】:

  • Zygar - 我同意你的观点,但我认为这不是他面临这个问题的原因。
  • 甘道夫,我敢打赌self.collectionList 中的观点有问题。即使不是,他也在与 tableView 实现作斗争。我认为以这种方式重写代码会比调试更快(而且我们正在提高代码质量)。他至少可以将removeFromSuperView循环移动到prepareForReuse
  • 同意你关于代码质量的观点,但这不是数组的问题,而是addSubview 的工作原理。请在下面查看我的答案。
  • 谢谢Zygar,我会改的。
  • 您好 Zygar,我已按照您的指示使用子类 UITableViewCell 创建自定义单元格。但是当我执行分配时,即cell.unit.text=apartment.unit; 应用程序崩溃了,并给出了这个错误:Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UITableViewCell label]: unrecognized selector sent to instance 0x7f9bc274b5e0' 在我删除该行之后,应用程序工作正常。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-11-28
  • 2017-01-01
  • 2011-02-09
  • 2012-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多