简体   繁体   English

删除索引 0 处的 CALayer

[英]Removing a CALayer at index 0

I've added a gradient layer:我添加了一个渐变层:

[theView.layer insertSublayer:gradient atIndex:0];

And later on in another method I want to remove this layer.后来在另一种方法中,我想删除这一层。 I figured I should get the array of sublayers then get the sublayer at index 0 and call removeFromSuperlayer on it.我想我应该获取子层数组,然后在索引 0 处获取子层并在其上调用 removeFromSuperlayer。 Is this the correct way or if not can you do it?这是正确的方法吗?如果不是,你能做到吗?

Cheers.干杯。

You can do it the way you described but it isn't so reliable.你可以按照你描述的方式来做,但它不是那么可靠。 The problem is that if you do anything with the sublayers in between the addition and removal, the index of the sublayer can change and you end up removing something you didn't want to.问题是,如果您在添加和删除之间对子图层进行任何操作,子图层的索引可能会发生变化,并且最终会删除您不想要的内容。

The best thing is to keep a reference to that layer and later when you want to remove it just call [theLayer removeFromSuperlayer]最好的办法是保留对该层的引用,稍后当您想删除它时,只需调用[theLayer removeFromSuperlayer]

Hope it helps希望能帮助到你

Funfunfun...趣趣...

There are two layer properties you can use (in either case you have to iterate over the layers):您可以使用两个图层属性(无论哪种情况,您都必须遍历图层):

  • CALayer.name "is used by some layout managers to identify a layer". CALayer.name “被一些布局管理器用来标识一个层”。 Set it to something reasonably guaranteed to be unique (eg "MyClassName.gradient").将其设置为合理保证唯一的内容(例如“MyClassName.gradient”)。
  • CALayer.style is a dictionary. CALayer.style是一本字典。 You can use keys which aren't used by CoreAnimation (eg NSMutableDictionary * d = [NSMutableDictionary dictionaryWithDictionary:layer.style]; [d setValue:[NSNumber numberWithBool:YES] forKey:@"MyClassName.gradient"]; layer.style = d; ).您可以使用 CoreAnimation 不使用的键(例如NSMutableDictionary * d = [NSMutableDictionary dictionaryWithDictionary:layer.style]; [d setValue:[NSNumber numberWithBool:YES] forKey:@"MyClassName.gradient"]; layer.style = d; )。 This might be useful to associate arbitrary data with a view (such as the index path of the cell containing a text field...).这可能有助于将任意数据与视图相关联(例如包含文本字段的单元格的索引路径...)。

(I'm assuming that [NSDictionary dictionaryWithDictionary:nil] returns the empty dictionary instead of returning nil or throwing an exception. The corresponding thing is true for [NSArray arrayWithArray:nil] .) (我假设[NSDictionary dictionaryWithDictionary:nil]返回空字典,而不是返回 nil 或抛出异常。相应的事情对于[NSArray arrayWithArray:nil]是正确的。)

However, the extra code complexity, performance penalty, and chance of getting it wrong probably outweigh the small decrease in memory usage.然而,额外的代码复杂性、性能损失和出错的机会可能超过内存使用量的小幅下降。 4 bytes per view is not that much if you have a handful of views (and even if you have loads, 4 bytes is the memory used by a single pixel!).如果您有少量视图,每个视图 4 个字节并不算多(即使您有负载,4 个字节也是单个像素使用的内存!)。

Swift has some really simple solutions for this: Swift 有一些非常简单的解决方案:

// SWIFT 4 update
func removeSublayer(_ view: UIView, layerIndex index: Int) {
    guard let sublayers = view.layer.sublayers else {
        print("The view does not have any sublayers.")
        return
    }
    if sublayers.count > index {
        view.layer.sublayers!.remove(at: index)
    } else {
        print("There are not enough sublayers to remove that index.")
    }
}
// Call like so
removeSublayer(view, layerIndex: 0)

Just remember, the sublayers are treated as an array, so if you have a count of 2, then 2 == 1 in the index, hence removeAtIndex(1) .请记住,子层被视为一个数组,因此如果您的计数为 2,则索引中的 2 == 1,因此removeAtIndex(1)

There are a whole heap of options available for editing sublayers.有一整套选项可用于编辑子图层。 Simply stop typing after sublayers!.只需在sublayers!.之后停止输入即可sublayers!. and check them out.并检查它们。

Old Post.. but this may be helpful for someone...旧帖子..但这可能对某人有帮助......

My implementation of removing/replacing a CALayer.我删除/替换 CALayer 的实现。 Using the Calayer.name as tc.使用 Calayer.name 作为 tc。 describes above.上面描述。

CAGradientLayer *btnGradient = [CAGradientLayer layer];
btnGradient.frame = button.bounds;
btnGradient.name = @"gradient";
btnGradient.colors = nil;
btnGradient.colors = [NSArray arrayWithObjects:
                      (id)[[VOHelper getButtonColor:kSchemeBorder] CGColor],
                      (id)[[VOHelper getButtonColor:kSchemeButton] CGColor],
                      nil];

if ([[[[button.layer sublayers] objectAtIndex:0] name] isEqualToString:@"gradient"]){
       [button.layer replaceSublayer:[[button.layer sublayers] objectAtIndex:0] with:btnGradient];
}
else{
    [button.layer insertSublayer:btnGradient atIndex:0];
}

Swift 4斯威夫特 4

  self.view.layer.sublayers = self.view.layer.sublayers?.filter { theLayer in
        !theLayer.isKind(of: CAGradientLayer.classForCoder())
  }

This worked for me Swift 5这对我有用 Swift 5

    if let _ = self.layer.sublayers?.first as? CAGradientLayer {
        print("Debug: Gradient sublayer Found.")
        self.layer.sublayers?[0] = gradient
    }
    else {
        print("Debug: Non Gradient Layer Found in Sublayer 0.")
        self.layer.insertSublayer(gradient, at: 0)
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM