CAGradientLayer 没有从视图中删除自我
Posted
技术标签:
【中文标题】CAGradientLayer 没有从视图中删除自我【英文标题】:CAGradientLayer not removing self from view 【发布时间】:2016-03-02 18:04:37 【问题描述】:我创建一个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:^
];
为什么会发生这种情况,我还不确定。
【问题讨论】:
你能显示日志输出吗?不是我不相信你什么的,而是…… 哦,还有:这是否偶然发生在表格视图的单元格中?如果是这样,您是否还记得考虑到细胞被重复使用的事实? 将添加日志,不,这是我创建的自定义子类UIView
“单元格”,用于放置在UIScrollView
中
嗯。好吧,我向你保证removeFromSuperlayer
确实删除了该层。您是否尝试过在该例程中放置断点?也许事情并没有按照你的预期进行。也许你不小心多次添加了渐变,所以现在渐变被移除了,但它后面还有另一个剩余的渐变。无论问题是什么,它似乎都没有出现在您在此处显示的代码中......
宾果游戏,我认为您在这里有所作为。我查看 self.contentView.layer.sublayers 并且那里仍然存在不应该的渐变。看起来正在添加 2 个渐变。看起来该方法被调用了两次,因此添加了 2 个渐变并保持 1 个被引用。感谢您帮助我找到问题。
【参考方案1】:
所以渐变失去了对其插入位置的引用。但我不知道如何或为什么。
这不是“失去参考”。您似乎对self.gradientLayer
有强烈的引用。你已经从它的超层中删除了self.gradientLayer
。但是您在强参考中保留了它。现在你要它的超层,很自然,它没有;你删除了它。因此,在界面中看到的渐变层与您正在与之交谈的渐变层不相同。这个故事中有(至少)两个渐变层。事情已经不同步了,这让你感到困惑。但我向你保证,该层并没有表现异常。
【讨论】:
好的,失去参考是错误的术语。我听从了你的建议,还有一些额外的渐变没有被删除。我会更新的。 是的,你是对的。我删除了该层,然后检查了它的超层,这是非常愚蠢的事情。我应该在移除它之前检查它的超层。根据您的建议,看看是否有额外的渐变没有被删除,帮助我找出问题所在。我不明白为什么这是一个问题,但我确实有解决办法。谢谢! 对不起,我有一个坏习惯,即投票并认为是接受。【参考方案2】:尝试这样做:
for (CALayer *layer in self.contentView.layer.sublayers)
if([layer isKindOfClass:[GradientLayer class]])
[layer removeFromSuperlayer];
【讨论】:
以上是关于CAGradientLayer 没有从视图中删除自我的主要内容,如果未能解决你的问题,请参考以下文章
如何在 iOS swift 运行时更新 CAGradientLayer 颜色?
为啥我不能在 ARC 中使用自定义颜色创建 CAGradientLayer?