Удаление CALayer с индексом 0
Я добавил слой градиента:
[theView.layer insertSublayer:gradient atIndex:0];
И позже в другом методе я хочу удалить этот слой. Я решил, что должен получить массив подслоев, затем получить подуровень с индексом 0 и называть removeFromSuperlayer. Правильно ли это, или если вы не можете это сделать?
Приветствия.
Ответы
Ответ 1
Вы можете сделать это так, как вы описали, но это не так надежно. Проблема в том, что если вы делаете что-либо с подслоями между добавлением и удалением, индекс подслоя может измениться, и вы в конечном итоге удалите то, что вы не хотели.
Лучше всего держать ссылку на этот слой, а позже, когда вы хотите удалить его, просто вызовите [theLayer removeFromSuperlayer]
Надеюсь, что это поможет
Ответ 2
Funfunfun...
Есть два свойства слоя, которые вы можете использовать (в любом случае вам нужно перебирать слои):
-
CALayer.name
"используется некоторыми менеджерами компоновки для идентификации слоя". Установите для него что-то разумно гарантированное уникальное (например, "MyClassName.gradient" ).
-
CALayer.style
- словарь. Вы можете использовать ключи, которые не используются CoreAnimation (например, NSMutableDictionary * d = [NSMutableDictionary dictionaryWithDictionary:layer.style]; [d setValue:[NSNumber numberWithBool:YES] forKey:@"MyClassName.gradient"]; layer.style = d;
). Это может быть полезно связать произвольные данные с представлением (например, путь индекса ячейки, содержащей текстовое поле...).
(Я предполагаю, что [NSDictionary dictionaryWithDictionary:nil]
возвращает пустой словарь вместо того, чтобы возвращать nil или бросать исключение. Соответствующая вещь верна для [NSArray arrayWithArray:nil]
.)
Тем не менее, сложность дополнительного кода, снижение производительности и вероятность его неправильного использования, вероятно, перевешивают небольшое снижение использования памяти. 4 байта на просмотр не так много, если у вас есть несколько представлений (и даже если у вас есть нагрузки, 4 байта - это память, используемая одним пикселем!).
Ответ 3
Старый пост.. но это может быть полезно для кого-то...
Моя реализация удаления/замены CALayer. Использование Calayer.name как tc. описано выше.
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];
}
Ответ 4
У 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)
Помните, что подслои обрабатываются как массив, поэтому, если у вас есть счетчик 2, то 2 == 1 в индексе, следовательно, removeAtIndex(1)
.
Существует целая куча параметров, доступных для редактирования подслоев. Просто перестаньте печатать после sublayers!.
и проверить их.
Ответ 5
Swift 4
self.view.layer.sublayers = self.view.layer.sublayers?.filter { theLayer in
!theLayer.isKind(of: CAGradientLayer.classForCoder())
}