在重用的原型单元格中多次应用渐变蒙版

Gradient Mask is applied multiple times in reused prototype cell

我有一个带有客户 UITableViewCell class 的表格视图 - 这是在 Storyboard/Builder 中作为原型单元格创建的。

因为我的单元格链接到 Storyboard 原型,所以我按如下方式引用它(cellIdentifier 与原型单元格上的 ID 匹配):

EventsListTableViewCell *cell = (EventsListTableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];

因此,单元格总是初始化并准备就绪(我不能使用 "if (cell == nil{...} ")

很好,但是我想在我的单元格中添加一个渐变层,这是我在 cellForRowAtIndex:

中所做的
gradientMask = [CAGradientLayer layer];
gradientMask.frame = cell.eventImage.layer.bounds;

gradientMask.startPoint = CGPointMake(0.5, 0.2);
gradientMask.endPoint = CGPointMake(0.5, 1.0);
gradientMask.colors = [NSArray arrayWithObjects:
                       (id)[[UIColor colorWithRed:0.0f green:0.0f blue:1.0f alpha:0.0f] CGColor],

                       (id)[[UIColor colorWithRed:0.0f green:0.0f blue:1.0f alpha:1.0f] CGColor],nil];
[cell.eventImage.layer insertSublayer:gradientMask atIndex:0];

这里的问题是,每次重新使用单元格都会应用 gradientMask,所以当我向下滚动时,它会变得越来越暗

我知道我只需要在第一次创建单元格时应用此 gradientMask 一次,但是我不确定在哪里调用此代码,因为我从来没有 'init' 单元格(这是由故事板)

我确实有这个单元格的自定义 class,但它只包含属性而没有方法?

有多种实现方法:

1- 属性 in UITableViewCell subclass

在 EventsListTableViewCell class 中创建一个 属性,它将保存对 gradientMask 的引用:

@interface EventsListTableViewCell : UITableViewCell

@property (weak, nonatomic) CAGradientLayer *gradientMask;

@end

然后在cellForRowAtIndexPath:方法中:

if (!cell.gradientMask) {
    gradientMask = [CAGradientLayer layer];
    gradientMask.frame = cell.eventImage.layer.bounds;

    gradientMask.startPoint = CGPointMake(0.5, 0.2);
    gradientMask.endPoint = CGPointMake(0.5, 1.0);
    gradientMask.colors = [NSArray arrayWithObjects:
                           (id)[[UIColor colorWithRed:0.0f green:0.0f blue:1.0f alpha:0.0f] CGColor],

                           (id)[[UIColor colorWithRed:0.0f green:0.0f blue:1.0f alpha:1.0f] CGColor],nil];
    [cell.eventImage.layer insertSublayer:gradientMask atIndex:0];
    cell.gradientMask = gradientMask;
}

这将确保 gradientMask 仅初始化一次。

2-name propertyCALayer

这样,您就不需要创建 属性,一切都可以在 cellForRowAtIndexPath: 方法本身中处理。

BOOL gradientFound = NO;

for (CALayer *layer in cell.eventImage.layer.sublayers)
{
    if ([layer.name isEqualToString:@"gradientLayer"])
    {
        gradientFound = YES;
        break;
    }
}

if (!gradientFound)
{
    gradientMask = [CAGradientLayer layer];
    gradientMask.frame = cell.eventImage.layer.bounds;
    gradientMask.name = @"gradientLayer";               //Set the name
    gradientMask.startPoint = CGPointMake(0.5, 0.2);
    gradientMask.endPoint = CGPointMake(0.5, 1.0);
    gradientMask.colors = [NSArray arrayWithObjects:
                           (id)[[UIColor colorWithRed:0.0f green:0.0f blue:1.0f alpha:0.0f] CGColor],

                           (id)[[UIColor colorWithRed:0.0f green:0.0f blue:1.0f alpha:1.0f] CGColor],nil];
    [cell.eventImage.layer insertSublayer:gradientMask atIndex:0];

}

3- 在 UITableViewCell subclass 本身中声明 gradienLayer

这是最简洁的方法,因为它还将与单元格相关的代码隔离在 class 中。您可以在 awakeFromNib 方法中初始化单元格。

@implementation EventsListTableViewCell
{
    CAGradientLayer *gradientMask;
}

-(void)awakeFromNib
{
    gradientMask = [CAGradientLayer layer];
    gradientMask.frame = cell.eventImage.layer.bounds;

    gradientMask.startPoint = CGPointMake(0.5, 0.2);
    gradientMask.endPoint = CGPointMake(0.5, 1.0);
    gradientMask.colors = [NSArray arrayWithObjects:
                           (id)[[UIColor colorWithRed:0.0f green:0.0f blue:1.0f alpha:0.0f] CGColor],

                           (id)[[UIColor colorWithRed:0.0f green:0.0f blue:1.0f alpha:1.0f] CGColor],nil];
    [self.eventImage.layer insertSublayer:gradientMask atIndex:0];
}

@end

由于您是自己从故事板文件中添加这一层,因此在 cellReuse 周期内该层将被删除。你必须手动完成。
我通常为单元格创建一个子类并覆盖 prepareForReuse 方法,在该方法中我删除了我在那里添加的所有自定义视图和图层。这样一切都会顺利进行。
并且不要忘记将您的子视图仅添加到单元格的 contentView 属性。