UITableView分隔线的奇怪行为

18

我有一个简单样式的表格,其中包含多个部分。

症状:当表格首次加载时,每个单元格都像往常一样具有其分隔符,除了每个部分中的最后一个单元格(即在标题“之前”的位置)。但是,在滚动时,某些单元格上会出现分隔符。此外,如果选择一个单元格,然后取消选择,则分隔符将出现。

打印查看层次结构显示,干净的启动状态下,每个部分中的最后一个单元格的分隔符视图是隐藏的,因此我会认为这是正常行为:

<_UITableViewCellSeparatorView: 0x145b1990; 
    frame = (0 47.5; 320 0.5); 
    hidden = YES; 
    layer = <CALayer: 0x145b2950>>

有时滚动并选择单元格,就会移除这个隐藏属性,分隔线就会出现。

我最初的假设是我做错了什么,但这甚至在最基本的hello world应用程序中也会发生:

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.tableView reloadData];
}

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

- (NSInteger)tableView:(UITableView *)tableView 
    numberOfRowsInSection:(NSInteger)section {
    return 2;
}

- (NSString *)tableView:(UITableView *)tableView 
    titleForHeaderInSection:(NSInteger)section {
    return @"test";
}

- (UITableViewCell *)tableView:(UITableView *)tableView 
    cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSString *reuseIdentifier = @"TestCell";
    UITableViewCell *cell = [tableView 
        dequeueReusableCellWithIdentifier:reuseIdentifier];
    return cell;
}

屏幕截图(左边:开始后;右边:选择单元格后):

start after selecting a cell

这是苹果方面的错误还是我漏掉了什么?例如,在iOS的联系人应用程序中,分隔符从不隐藏在部分标题上方...

**更新:**

在原生音乐应用中能够复现此问题:例如“歌曲”标签页中没有分隔符。选择任何一节的第一个单元格,然后取消选择,分隔符就出现了。

额外信息:iOS 7.1


你是如何隐藏分隔符的? - Enrico Susatyo
我没有这样做;表格中每个部分的最后一个单元格中都隐藏了分隔符。 - Robert B.
嗯,我确实没有见过这种行为。你能否给我们展示一个演示此问题的示例项目?可以放在GitHub或Dropbox上吗? - Enrico Susatyo
我刚刚发现,我可以在原生音乐应用程序中重现这个问题。在歌曲选项卡中,我滚动到一个部分标题(例如字母E)。在部分标题上方没有分隔符。我长按部分E中的第一个单元格足够长时间以使其被突出显示,然后滑动取消选择。在部分E上方出现了分隔符。iOS 7.1 - Robert B.
啊,我现在明白你的意思了。这可能是一个苹果的 bug。试着在 radar 里记录一下吧。 - Enrico Susatyo
我很害怕听到那个... 无论如何还是谢谢。 - Robert B.
4个回答

9

由于这是iOS 7.1的一个bug,我建议采用以下方法作为解决方案:隐藏内置分隔线并在每个单元格底部显示自定义分隔线。

隐藏内置分隔线:

[self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];

显示自定义分隔线:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSString *reuseIdentifier = @"TestCell";
    XXYourCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
    cell.customSeparatorView.hidden = (indexPath.row == ([self numberOfRowsInSection:indexPath.section] - 1));
    return cell;
}

1
这是一个不错的解决方法。我必须在代码中创建自定义分隔符视图;Interface Builder 无法正确处理0.5pt视图高度...看不到任何性能问题。 - Robert B.
请勿使用分数来表示视图的大小/位置,考虑在非Retina显示屏上如何呈现... - Tom Susel
幸运的是,这个问题出现的项目是iOS 7.0+和仅限iPhone;因此需要支持的所有设备都有视网膜屏幕。但是要注意合法警告。 - Robert B.

4

在我的情况下,是自定义UITableViewCell上的 Clip To Bounds 导致的问题。不小心从故事板中取消选择了它。然后再将Clip To Bounds设置为true即可解决此问题。

输入图片说明


太棒了,非常感谢!这对我起作用了,你帮我节省了时间 :) - Yogesh Patel
它对我有效,但我不理解“剪切到边界”的意思,你能解释一下吗?为什么这对我有效呢? - Yogesh Patel
clipsToBounds 的官方文档。在一般场景下,当设置为 true 时,如果子视图超出父视图,则会裁剪它。 - Shad
好的,谢谢 @shad - Yogesh Patel

2

由于iOS 7及以上版本出现此问题,我建议按照以下棘手的步骤来避免这种情况。

隐藏tableView默认的单元格分隔符:

    [self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];

将自定义视图添加到您的自定义单元格中:

CustomCell.h
@property (nonatomic,strong) UIView* cellSeperatorView;

CustomCell.m
@synthesize cellSeperatorView;


-(UIView *)cellSeperatorView{
      if (!cellSeperatorView) {
          self.cellSeperatorView = [[UIView alloc]    initWithFrame:CGRectZero];
        [self.cellSeperatorView setBackgroundColor:[UIColor lightGrayColor]];
         [self addSubview:self.cellSeperatorView];
      }
      return cellSeperatorView;
 }

-(void)prepareForReuse{

     self.cellSeperatorView = nil;

 }

-(void)layoutSubviews{
    [super layoutSubviews];
    [self.cellSeperatorView setFrame:CGRectMake(0, 100, self.width, 1)];
}

@ShahzaibMaqbool 很高兴为您服务.. :) - be.with.veeresh

0

虽然我的情况有些不同,但我也遇到了这个问题。我的单元格处于编辑模式,但这似乎并不重要。在我的情况下,我不希望在选择单元格后显示底部的_UITableViewCellSeparatorView,因此在查看单元格的子视图NSLog(@"%@", [cell.subviews[0] subviews]);后,我发现了以下内容:

(
    "<_UITableViewCellSeparatorView: 0x9df7f30; frame = (0 99; 280 1); layer = <CALayer: 0x9dfb800>>",
    "<UITableViewCellContentView: 0x9d65950; frame = (38 0; 242 99.5); opaque = NO; gestureRecognizers = <NSArray: 0x9d2e0d0>; layer = <CALayer: 0x9de8290>>",
    "<_UITableViewCellSeparatorView: 0x9dfab90; frame = (0 99.5; 280 0.5); layer = <CALayer: 0x9dfb7d0>>",
    "<UITableViewCellEditControl: 0x9df3f60; frame = (0 0; 47 100); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x9d91370>>",
    "<UIView: 0x9df4470; frame = (0 98; 280 3); layer = <CALayer: 0x9df44d0>>",
    "<UIView: 0x9d35f10; frame = (0 98; 280 3); layer = <CALayer: 0x9d39e20>>"
)

通过使用这个方法,可以更轻松地找到并摆脱烦人的分隔符视图。

[[[cell.subviews[0] subviews] objectAtIndex:2] setBackgroundColor:[UIColor clearColor]];

出于某种原因,我对顶部分隔视图没有问题,很可能是因为每个部分的标题都有一个深色背景颜色,可以隐藏分隔视图,但如果您想要覆盖它们,您可以添加以下代码

[[[cell.subviews[0] subviews] firstObject] setBackgroundColor:[UIColor clearColor]];

请注意,我将这段代码放在了我的 didHighlightRowAtIndexPath 代理方法中。此外,我的单元格 selectionStyle 被设置为默认样式。希望这对某些人有所帮助!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接