Removing all CALayer's sublayers

0 votes
asked Jan 14, 2010 by radex

I have trouble with deleting all of layer's sublayers. I currently do this manually, but that brings unnecessary clutter. I found many topics about this in google, but no answer.

I tried to do something like this:

for(CALayer *layer in rootLayer.sublayers)
{
    [layer removeFromSublayer];
}

but it didn't work.

Also, i tried to clone rootLayer.sublayers into separate NSArray, but result was the same.

Any ideas?

Edit:

I thought it works now, but I was wrong. It works good with CALayers, but it doesn't work with CATextLayers. Any ideas?

14 Answers

0 votes
answered Jan 1, 2010 by pascal-bourque

The simplest way to remove all sublayers from a layer is to set the sublayer property to nil:

rootLayer.sublayers = nil;

0 votes
answered Jan 14, 2010 by ben-gottlieb

The following should work:

for (CALayer *layer in [[rootLayer.sublayers copy] autorelease]) {
    [layer removeFromSuperlayer];
}
0 votes
answered Jan 15, 2010 by katokichisoft

How about using reverse enumeration?

NSEnumerator *enumerator = [rootLayer.sublayers reverseObjectEnumerator];
for(CALayer *layer in enumerator) {
    [layer removeFromSuperlayer];
}

Because the group in sublayers are changed during enumeration, if the order is normal. I would like to know the above code's result.

0 votes
answered Jan 18, 2011 by tomh
[rootLayer.sublayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)];
0 votes
answered Jan 21, 2014 by nestor

Indiscriminately removing all sublayers causes nasty crashes in iOS 7, which can occur much later in the program's execution. I have tested this thoroughly using both rootLayer.sublayers = nil and [rootLayer.sublayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)]. There must be a system-created layer that's getting messed up.

You have to keep your own array of layers and remove them yourself:

[myArrayOfLayersIAddedMyself makeObjectsPerformSelector:@selector(removeFromSuperlayer)];
0 votes
answered Jan 28, 2014 by zero3nna

I tried to delete just the first sublayer at index 0 and this worked:

- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    if ([cell.contentView.layer.sublayers count] != 0) {
        [[cell.contentView.layer.sublayers objectAtIndex:0] removeFromSuperlayer];
    }
0 votes
answered Jan 16, 2015 by amit-limje

Both setting self.view.layer.sublayers = nil and [layer removeFromSuperlayer] will result in crash if UIView contains any subview. Best way to remove CALayer from superLayer is by maintaining an array of layers. For instance that array is arrayOfLayers,

Everytime you add a layer on UIView.sublayer add that layer in this array ie. [

arrayOfLayers addObject:layer];
[self.view.layer addSublayer:layer];

While removing just call this,

[arrayOfLayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)];
0 votes
answered Jan 17, 2015 by kafu

Calling rootLayer.sublayers = nil; can cause a crash (e.g. if, under iOS 8, you call removeFromSuperview twice on the view owning rootLayer).

The right way should be:

[[rootLayer.sublayers copy] makeObjectsPerformSelector:@selector(removeFromSuperlayer)]

The call to copy is needed so that the array on which removeFromSuperlayer is iteratively called is not modified, otherwise an exception is raised.

0 votes
answered Jan 28, 2015 by us-david

For sure you can do:
self.layer.sublayers=nil;
as suggested by Pascal Bourque. But it's better to call the setter for sublayers property:
[self.layer setSublayers:nil];
To avoid any clean up issues if there might be.

0 votes
answered Jan 15, 2016 by pnavk

I had to do this in Xamarin/C#. I had a UITableViewCell with some CAShapeLayers for borders. All of the above options (including copying the Array and then removing layers caused a crash). The approach that worked for me:

When adding the CALayer, I gave it a name:

    var border = new CALayer();
    border.BackgroundColor = color.CGColor;
    border.Frame = new  CGRect(x, y, width, height);
    border.Name = "borderLayerName";
    Layer.AddSublayer(border);

In PrepareForReuse on the UITableViewCell, I created a copy of the SubLayers property and removed anything that matched the name I assigned earlier:

    CALayer[] copy = new CALayer[Layer.Sublayers.Length];
    Layer.Sublayers.CopyTo(copy, 0);
    copy.FirstOrDefault(l => l.Name == "borderLayerName")?.RemoveFromSuperLayer();

No crashes.

Hope this helps!

Welcome to Q&A, where you can ask questions and receive answers from other members of the community.
Website Online Counter

...