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;你删除了它。因此,您在界面中看到的渐变层与您正在与之交谈的渐变层不同。这个故事中有(至少)两个个渐变层。事情变得不同步,这让你感到困惑。但是层没有异常,我向你保证。
我创建一个 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;你删除了它。因此,您在界面中看到的渐变层与您正在与之交谈的渐变层不同。这个故事中有(至少)两个个渐变层。事情变得不同步,这让你感到困惑。但是层没有异常,我向你保证。