Удаление 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())
  }