remove all subLayers from a view
Asked Answered
J

8

66

In an animation I added a lot of sublayers to a view, with:

[self.view.layer addSublayer:layer1];
[self.view.layer addSublayer:layer2];

....

I would like to remove all sublayers with an action. I already tried with this suggestion of a similar question:

rootLayer.sublayers = nil;

but it doesn't work...

Could you help me? Than you!

Joyjoya answered 28/5, 2012 at 19:48 Comment(0)
H
157

The sublayers property of a CALayer object returns a copy of the array. Setting it no nil does nothing about the sublayers. This however will do:

for (CALayer *layer in self.view.layer.sublayers) {
    [layer removeFromSuperlayer];
}

Or, in Swift

self.view.layer.sublayers?.forEach { $0.removeFromSuperlayer() }
Heartsease answered 28/5, 2012 at 20:6 Comment(10)
It seems I am mistaken. You can set the sublayers to an array prepopulated with CALayer objects. My solution is still correct, though. Also this oneliner should probably work (untested): [self.view.layer.sublayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)]Heartsease
@SveinHalvorHalvorsen That one line does work. Its much cleaner than a loopCorrespondent
Plus, it's sometimes problematic to mutate an array while iterating through it. Maybe it happens to work here, but in general it can be problematic.Richman
The sublayers property of CALayer returns a copy. However, so you're not mutating the array you're iterating over. Also, if an element of the array is no longer a sublayer of the layer by the time you call removeFromSuperLayer this has no side-effects unless the layer has been added as a sublayer to another layer.Heartsease
Although sublayers property of CALayer has "copy" attribute, this code causes crash with more than one sublayer (trying to mutate array while enumerating it). Explicitly copying sublayers array fixes this problem: for (CALayer *sublayer in [rootLayer.sublayers copy]) { [sublayer removeFromSuperlayer]; }Singlehanded
For swift version,it will be better if we can add check of ---- if layer.isKindOfClass(CAShapeLayer) { layer.removeFromSuperlayer() }Storied
this threw NSGenericExceptionHassan
@JoeBlow I reverted your edits. There is no reason to only remove CAShapeLayer. The original question does not mention shape layers, and this arbitrarily restricts the layers removed to one special kind. We want to remove all sublayers. The code above does not crash, and does not mutate the array while iterating.Heartsease
Big Thanks for you man, a week pass trying to solve this issue. just with your code everything is okay.Overbearing
Like we have tag in view is there any specific thing to identify specific layer ?Victual
M
33

Swift 3.0 & Swift 4.0

Set the sublayers property to nil to remove all sublayers from a view.

view.layer.sublayers = nil

also you can add

.removeAll()
Monochrome answered 18/4, 2017 at 10:33 Comment(1)
Worked for me, Dont know any downside of doing this. Should this be used rather than calling removeFromSuperLayer() for each sub layer? May be others can comment.Calliope
J
22

This worked for me and fixed the crash:

[self.view.layer.sublayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)]

I changed the view with my image UImageview, and the crash is gone.

Jokjakarta answered 16/9, 2013 at 15:46 Comment(0)
Z
6

For swift5 to remove CAShapeLayer from added view

guard let sublayers = self.view.layer.sublayers else { return }

for sublayer in sublayers where sublayer.isKind(of: CAShapeLayer.self) {
        sublayer.removeFromSuperlayer()
}
Zurek answered 29/7, 2020 at 11:16 Comment(0)
H
4

Swift 2.0:

    for layer: CALayer in self.view.layer.sublayers! {
        layer.removeFromSuperlayer()
    }

or

    self.view.layer.performSelector("removeFromSuperlayer")
Hopscotch answered 9/2, 2016 at 10:27 Comment(0)
C
2

Swift 5:

You can either remove the layer itself or iterate through them and do the following:

layer.removeAllAnimations()
layer.removeFromSuperlayer()
Cutthroat answered 29/10, 2019 at 17:24 Comment(0)
S
1

Swift 4.1

self.view.layer.sublayers?.removeAll()

or if in a UIView sub-class just

layer.sublayers?.removeAll()

Sunstone answered 6/9, 2018 at 12:27 Comment(2)
this crashes, any ideas whyAdroit
There's a gotcha here - beware that you didn't create a layer that you then subsequently try to access after removing all sublayers at another place in your code!Sunstone
L
0

If you want to delete all sublayers and add a new one, you can easily do:

rootLayer.sublayers = [layer1] // adding one layer

rootLayer.sublayers = [layer1, layer2, ...] // adding two or more layers

This could be helpful, if you work with tableview or collectionview cells. You don't need to call prepareForReuse for removing the sublayers.

Libidinous answered 7/4, 2019 at 21:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.