Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove imageView sublayer from TableViewCell

When I have an image I insert sublayer with CAGradientLayer,

...
layer.name = @"Gradient";
[cell.imageView.layer insertSublayer:layer atIndex:0];

and when there is no image for ImageView I need to remove this sublayer. I tried different ways with no success. The last I tried was

for (CALayer *layer in cell.imageView.layer.sublayers) {
    if ([layer.name isEqualToString:@"Gradient"]) {
        [layer removeFromSuperlayer];
    }

}

but it gives me an error:

CoreData: error: Serious application error.  An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:.  *** Collection <CALayerArray: 0xc1502e0> was mutated while being enumerated. with userInfo (null)
like image 770
Shmidt Avatar asked Feb 06 '12 14:02

Shmidt


1 Answers

The exception is thrown because you are changing the contents of the sublayers array while enumerating it with foreach loop. This is not something special to layers, a similar exception is thrown when you add/remove objects while enumerating any NSMutableArray.

You have various options to solve this issue

Solution 1: Stop enumerating as soon as you modify the array.

for (CALayer *layer in cell.imageView.layer.sublayers) {
    if ([layer.name isEqualToString:@"Gradient"]) {
        [layer removeFromSuperlayer];
        break;
    }
}

Solution 2: Do not enumerate the real array, instead use its copy.

NSArray* sublayers = [NSArray arrayWithArray:cell.imageView.layer.sublayers];
for (CALayer *layer in sublayers) {
    if ([layer.name isEqualToString:@"Gradient"]) {
        [layer removeFromSuperlayer];
    }
}

Solution 3: Use key value coding to keep a reference to the gradient layer.

Set it after inserting:

[cell.imageView.layer insertSublayer:layer atIndex:0];
[cell.imageView.layer setValue:layer forKey:@"GradientLayer"];

Retrieve and remove it

CALayer* layer = [cell.imageView.layer valueForKey:@"GradientLayer"];
[layer removeFromSuperlayer];
[cell.imageView.layer setValue:nil forKey:@"GradientLayer"];
like image 93
murat Avatar answered Oct 02 '22 20:10

murat