Удаление CALayer по индексу 0 - PullRequest
14 голосов
/ 23 ноября 2010

Я добавил градиентный слой:

[theView.layer insertSublayer:gradient atIndex:0];

И позже другим способом я хочу удалить этот слой.Я подумал, что должен получить массив подслоев, затем получить подуровень с индексом 0 и вызвать на нем removeFromSuperlayer.Это правильный путь или если нет, вы можете сделать это?

Приветствия.

Ответы [ 4 ]

17 голосов
/ 23 ноября 2010

Вы можете сделать это так, как вы описали, но это не так надежно.Проблема в том, что если вы сделаете что-нибудь с подуровнями между добавлением и удалением, индекс подслоя может измениться, и вы в конечном итоге удалите то, что не хотели.

Лучше всего сохранитьссылка на этот слой и позже, когда вы хотите удалить его, просто позвоните [theLayer removeFromSuperlayer]

Надеюсь, это поможет

9 голосов
/ 23 ноября 2010

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 голосов
/ 29 сентября 2016

У 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!. и проверьте их.

3 голосов
/ 22 сентября 2015

Old Post .. но это может быть полезно для кого-то ...

Моя реализация удаления / замены 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];
}
...