Удалить подслой imageView из TableViewCell - PullRequest
7 голосов
/ 06 февраля 2012

Когда у меня есть изображение, я вставляю подслой с помощью CAGradientLayer,

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

, и когда нет изображения для ImageView, мне нужно удалить этот подслой.Я пробовал разные способы безуспешно.Последнее, что я попробовал, было

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

}

, но выдает ошибку:

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)

1 Ответ

29 голосов
/ 06 февраля 2012

Исключение выдается, поскольку вы изменяете содержимое массива sublayers, перечисляя его с помощью цикла foreach.Это не является чем-то особенным для слоев, аналогичное исключение выдается при добавлении / удалении объектов при перечислении любого NSMutableArray.

У вас есть различные варианты решения этой проблемы

Решение 1: Прекратите перечисление, как только вы измените массив.

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

Решение 2: Не перечисляйте реальный массив, вместо этого используйте его копию.

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

Решение 3: Используйте кодирование значения ключа, чтобы сохранить ссылку на слой градиента.

Установите его после вставки:

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

Извлеките и удалите его

CALayer* layer = [cell.imageView.layer valueForKey:@"GradientLayer"];
[layer removeFromSuperlayer];
[cell.imageView.layer setValue:nil forKey:@"GradientLayer"];
...