CAGradientLayer 没有从视图中删除自己

CAGradientLayer not removing self from view

我创建一个 CAGradientLayer 并将其添加到 UIView:

CAGradientLayer *layer = [UIColor lightBlueSpreadGradient];
layer.frame = self.contentView.bounds;
layer.cornerRadius = self.contentView.layer.cornerRadius;
self.gradientLayer = layer;

[self.contentView.layer insertSublayer:layer atIndex:0];

我保留了对它的引用,以便以后删除它:

[self.gradientLayer removeFromSuperlayer];

但它实际上并没有自行删除。我知道它被调用了,取消选择方法中的其他所有内容都按预期工作:

-(void)setIsActive:(BOOL)isActive {
    _isActive = isActive;

    if (_isActive) {
        CAGradientLayer *layer = [UIColor lightBlueSpreadGradient];
        layer.frame = self.contentView.bounds;
        layer.cornerRadius = self.contentView.layer.cornerRadius;
        self.gradientLayer = layer;
        DLog(@"inserting self.gradientLayer: %@", self.gradientLayer);

        [self.contentView.layer insertSublayer:layer atIndex:0];
    }
    else {
        DLog(@"is active is false");
        DLog(@"removing overlay");

        DLog(@"self.gradientLayer: %@", self.gradientLayer);
        [self.gradientLayer removeFromSuperlayer];

    }
}

日志:

DEBUG | __31-[DatasetTrayCell setIsActive:]_block_invoke | inserting self.gradientLayer: <CAGradientLayer: 0x7e26cce0>
DEBUG | -[DatasetTrayCell setIsActive:] | is active is false
DEBUG | -[DatasetTrayCell setIsActive:] | removing overlay
DEBUG | -[DatasetTrayCell setIsActive:] | removing self.gradientLayer: <CAGradientLayer: 0x7e26cce0>

点击手势:

UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapDectected)];
singleTap.numberOfTapsRequired = 1;
singleTap.numberOfTouchesRequired = 1;

[self addGestureRecognizer:singleTap];

单击检测方法:

-(void)singleTapDectected {
    DLog(@"tap detected");

    if (self.isActive) {
        self.isActive = NO;
    }
    else {
        self.isActive = YES;
    }

}

日志:

DEBUG | -[DatasetTrayCell singleTapDectected] | tap detected

知道为什么它不会删除吗?

编辑:

好的,我发现了问题,但我不明白为什么会出现问题。所以我设置 isActive:

的完整方法
-(void)setIsActive:(BOOL)isActive {
    DLog(@"setting isActive");

    _isActive = isActive;

    if (_isActive) {
        if ([self.delegate respondsToSelector:@selector(datasetTrayCell:displayWithCompletionBlock:)]) {
            [self.delegate datasetTrayCell:self displayWithCompletionBlock:^{
                CAGradientLayer *layer = [UIColor lightBlueSpreadGradient];
                layer.frame = self.contentView.bounds;
                layer.cornerRadius = self.contentView.layer.cornerRadius;
                self.gradientLayer = layer;
                DLog(@"inserting self.gradientLayer: %@", self.gradientLayer);

                [self.contentView.layer insertSublayer:layer atIndex:0];
                DLog(@"self.gradientLayer.superlayer: %@", self.gradientLayer.superlayer);
                DLog(@"self.contentView.layer.sublayers: %@", self.contentView.layer.sublayers);

            }];
        }
    }
    else {
        if ([self.delegate respondsToSelector:@selector(datasetTrayCell:removeWithCompletionBlock:)]) {
            [self.delegate datasetTrayCell:self removeWithCompletionBlock:^{
                DLog(@"self.contentView.layer.sublayers: %@", self.contentView.layer.sublayers);
                [self.gradientLayer removeFromSuperlayer];
                DLog(@"self.gradientLayer.superlayer: %@", self.gradientLayer.superlayer);
                DLog(@"removing self.gradientLayer: %@", self.gradientLayer);
            }];
        }
        else {
            DLog(@"delegate does not respond to removeOverlayWithCompletionBlock");
        }
    }
}

CAGradientLayer 在块中创建的事实导致它被创建两次:

DEBUG | __31-[DatasetTrayCell setIsActive:]_block_invoke | inserting self.gradientLayer: <CAGradientLayer: 0x787bdc80>
DEBUG | __31-[DatasetTrayCell setIsActive:]_block_invoke | self.gradientLayer.superlayer: <CALayer: 0x7db473f0>
DEBUG | __31-[DatasetTrayCell setIsActive:]_block_invoke | self.contentView.layer.sublayers: (
    "<CAGradientLayer: 0x787bdc80>",
    "<CALayer: 0x787bd750>"
)

又一次:

DEBUG | __31-[DatasetTrayCell setIsActive:]_block_invoke | inserting self.gradientLayer: <CAGradientLayer: 0x78631ce0>
DEBUG | __31-[DatasetTrayCell setIsActive:]_block_invoke | self.gradientLayer.superlayer: <CALayer: 0x7db473f0>
DEBUG | __31-[DatasetTrayCell setIsActive:]_block_invoke | self.contentView.layer.sublayers: (
    "<CAGradientLayer: 0x78631ce0>",
    "<CAGradientLayer: 0x787bdc80>",
    "<CALayer: 0x787bd750>"
)

一旦我从代码块中删除那段代码,它就会正常运行(它只会创建 1 个渐变):

-(void)setIsActive:(BOOL)isActive {
    DLog(@"setting isActive");

    _isActive = isActive;

    if (_isActive) {
        CAGradientLayer *layer = [UIColor lightBlueSpreadGradient];
        layer.frame = self.contentView.bounds;
        layer.cornerRadius = self.contentView.layer.cornerRadius;
        self.gradientLayer = layer;

        [self.contentView.layer insertSublayer:layer atIndex:0];

        if ([self.delegate respondsToSelector:@selector(datasetTrayCell:displayWithCompletionBlock:)]) {
            [self.delegate datasetTrayCell:self displayWithCompletionBlock:^{
            }];
        }
    }
    else {
        [self.gradientLayer removeFromSuperlayer];

        if ([self.delegate respondsToSelector:@selector(datasetTrayCell:removeWithCompletionBlock:)]) {
            [self.delegate datasetTrayCell:self removeWithCompletionBlock:^{
            }];
        }
    }
}

为什么会这样,我还不确定。

尝试改为:

for (CALayer *layer in self.contentView.layer.sublayers) {
    if([layer isKindOfClass:[GradientLayer class]])
    {
        [layer removeFromSuperlayer];

    }
}

So the gradient is losing its reference to where it was inserted to. But I haven't a clue how or why.

不是 "losing its reference"。您似乎对 self.gradientLayer 有很强的参考。并且您已经从其超级层中删除了 self.gradientLayer。但是你在你的强参考中保留了它。现在你要求它的超级层,自然而然地,它有 none;你删除了它。因此,您在界面中看到的渐变层与您正在与之交谈的渐变层不同。这个故事中有(至少)两个个渐变层。事情变得不同步,这让你感到困惑。但是层没有异常,我向你保证。