记一个selectedBackgroundView的坑

今天在解 bug 的时候遇到了一个非常奇怪的问题,单击 cell 进行选中的时候,cell 中的一条用 UIView 实现的横线 seperateLineView 消失了。

看了一圈所有跟这个 seperateLineView 相关的代码,却看不出任何可能改动到包括 framealphahidden 的地方。这个时候就想起了关门打狗。 命名一个新的 UIView 的子视图 TestView :

@interface TestView : UIView

@end

@implementation TestView

- (void)setBackgroundColor:(UIColor *)backgroundColor {
    [super setBackgroundColor:backgroundColor];
    // 在这里打上一个断点
    NSLog(@"backgroundColor: %@", backgroundColor);
}

@end

接着操作之前的复现路径,发现在某次的断点中,backgroundColorUIExtendedGrayColorSpace 0 0,这个时候查看了一下调用栈如下(只提取关键部分):

    frame #1: 0x000000010fa4b198 UIKit`-[UITableViewCell _setOpaque:forSubview:] + 1712
    frame #2: 0x000000010fa4b07b UIKit`-[UITableViewCell _setOpaque:forSubview:] + 1427
    frame #3: 0x000000010fa4b07b UIKit`-[UITableViewCell _setOpaque:forSubview:] + 1427
    frame #4: 0x000000010fa4b07b UIKit`-[UITableViewCell _setOpaque:forSubview:] + 1427
    frame #5: 0x000000010fa4bb92 UIKit`-[UITableViewCell showSelectedBackgroundView:animated:] + 1626
    frame #6: 0x000000010fa4bd1b UIKit`-[UITableViewCell setHighlighted:animated:] + 297
    frame #7: 0x000000010f7dd23a UIKit`-[UITableView highlightRowAtIndexPath:animated:scrollPosition:] + 644   

从而得知,-setBackgroundColor: 的调用是来自于 -[UITableViewCell _setOpaque:forSubview:] ,而 -[UITableViewCell _setOpaque:forSubview:] 在当 一个被设置了 selectedBackgroundViewcell 被选中的时候会被调用到。

换句话说,如果我们给一个cell 设置了 selectedBackgroundView,那么这个 cell 在被选中的时候,系统会将它的子视图的背景色全都设置为 clearColor。这其中的原因我们不得而知,不过大概可以猜到的是,这应该是属于对 cell 的一种优化,为了有更快渲染速度吧。

在知道了原因之后,我们就有两种解决办法了,一种是在 cell 每次被选中的时候重新设置 seperateLineView 的背景色,这个感觉不是很优雅;另一种则是换个实现。 使用 UIImageview 实现 seperateLineView,而不是通过设置 UIView 的背景色,这样就不会被重置掉了。

Show Comments