Удаление всех Подслоев CALayer
У меня возникли проблемы с удалением всех подслоев слоя. В настоящее время я делаю это вручную, но это приносит ненужную. Я нашел много тем об этом в google, но ответа нет.
Я пытался сделать что-то вроде этого:
for(CALayer *layer in rootLayer.sublayers) { [layer removeFromSublayer]; }
но это не сработало.
кроме того, я пытался клонировать rootLayer.подслои в отдельный NSArray, но результат был тот же.
какие идеи?
Edit:
Я думал, что это работает сейчас, но я неправый. Он хорошо работает с CALayers, но он не работает с CATextLayers. Есть идеи?
14 ответов:
самый простой способ удалить все подслои из слоя-установить свойство подслоя равным nil:
rootLayer.sublayers = nil;
следующее должно работать:
for (CALayer *layer in [[rootLayer.sublayers copy] autorelease]) { [layer removeFromSuperlayer]; }
вызов
rootLayer.sublayers = nil;
может вызвать сбой (например, если в iOS 8 вы дважды вызываете removeFromSuperview в представлении, владеющемrootLayer
).правильный путь должен быть:
[[rootLayer.sublayers copy] makeObjectsPerformSelector:@selector(removeFromSuperlayer)]
вызов
copy
- это необходимо, чтобы массив, на которомremoveFromSuperlayer
многократно называют не изменяется, в противном случае возникает исключение.
Как насчет использования обратного перечисления?
NSEnumerator *enumerator = [rootLayer.sublayers reverseObjectEnumerator]; for(CALayer *layer in enumerator) { [layer removeFromSuperlayer]; }
потому что группы в подслоях изменяются во время перечисления, если порядок нормальный. Я хотел бы знать результат вышеуказанного кода.
без разбора удаление всех подслоев вызывает неприятные сбои в iOS 7, которые могут произойти гораздо позже при выполнении программы. Я проверил это тщательно, используя оба
rootLayer.sublayers = nil
и[rootLayer.sublayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)]
. Там должен быть системный слой, который запутывается.вы должны сохранить свой собственный массив слоев и удалить их самостоятельно:
[myArrayOfLayersIAddedMyself makeObjectsPerformSelector:@selector(removeFromSuperlayer)];
Я попытался удалить только первый подслой с индексом 0, и это сработало:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { if ([cell.contentView.layer.sublayers count] != 0) { [[cell.contentView.layer.sublayers objectAtIndex:0] removeFromSuperlayer]; }
Я должен был сделать это в Xamarin/C#для. У меня был
UITableViewCell
СCAShapeLayers
за границы. Все вышеперечисленные параметры (включая копирование массива и последующее удаление слоев) вызвали сбой. Подход, который работал для меня:при добавлении
CALayer
, Я дал ему имя:var border = new CALayer(); border.BackgroundColor = color.CGColor; border.Frame = new CGRect(x, y, width, height); border.Name = "borderLayerName"; Layer.AddSublayer(border);
на
PrepareForReuse
наUITableViewCell
Я создал копиюSubLayers
свойство и удалил все, что соответствовало имени, которое я назначил ранее:CALayer[] copy = new CALayer[Layer.Sublayers.Length]; Layer.Sublayers.CopyTo(copy, 0); copy.FirstOrDefault(l => l.Name == "borderLayerName")?.RemoveFromSuperLayer();
нет крахи.
надеюсь, что это помогает!
я столкнулся с той же проблемой и нашел много решений, но ни одно из них не является идеальным.
Наконец-то от над ответом pnavk у меня есть идея. Там код предназначен для пользователей Xamarin/C#.
Версия iOS может быть как ниже:Swift 2.3
if rootLayer.sublayers?.count > 0 { rootLayer.sublayers?.forEach { if .name == "bottomBorderLayer" { .removeFromSuperlayer() } } } let border = CALayer() let height = CGFloat(1.0) border.borderColor = UIColor.blackColor().CGColor border.borderWidth = height border.frame = CGRectMake(0, self.frame.size.height - height, self.frame.size.width, self.frame.size.height) border.name = "bottomBorderLayer" rootLayer.addSublayer(border) rootLayer.masksToBounds = true
Сif (rootLayer.sublayers.count > 0) { for (CALayer *layer in rootLayer.sublayers) { if ([layer.name isEqualToString:@"bottomBorderLayer"]) { [layer removeFromSuperlayer]; } } } CALayer *border = [[CALayer alloc] init]; CGFloat height = 1.0; border.borderColor = [UIColor blackColor].CGColor; border.borderWidth = height; border.frame = CGRectMake(0, self.view.frame.size.height - height, self.view.frame.size.width, self.view.frame.size.height); border.name = @"bottomBorderLayer"; [rootLayer addSublayer:border]; rootLayer.masksToBounds = TRUE;
приведенный выше код будет работать только для нижней границы. Вы можете изменить сторону границы согласно вашему требование.
Здесь перед добавлением любого слоя к контроллеру я просто запускаю цикл for, чтобы проверить, применяется ли какая-либо граница или нет?
Для идентификации ранее добавленной границы я использую свойство name CALayer. И сравните этот слой перед удалением из подслоев.
Я пробовал тот же код перед использованием свойства name, но он создает случайный сбой. Но после использования свойства name и сравнения имени перед удалением решит проблему сбоя.
Я надеюсь, что это будет помогите кому-нибудь.
как параметр
self.view.layer.sublayers = nil
и[layer removeFromSuperlayer]
приведет к аварии, еслиUIView
содержит подпанели. Лучший способ удалитьCALayer
от суперслоя путем поддержания массива слоев. Например, что массив arrayOfLayers,каждый раз, когда вы добавляете слой на
UIView.sublayer
добавьте этот слой в этот массив...[arrayOfLayers addObject:layer]; [self.view.layer addSublayer:layer];
при удалении просто называем это
[arrayOfLayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)];
конечно, вы можете сделать:
self.layer.sublayers=nil;
как предложил Паскаль Бурк. Но лучше вызвать сеттер для свойства подслоев:[self.layer setSublayers:nil];
Чтобы избежать каких-либо проблем с очисткой, если они могут быть.
для swift3+,вы можете использовать это.
yourView.layer.sublayers?.removeAll(keepingCapacity: true)
смотрите здесь: Apple API Reference
или вы можете:
yourView.layer.sublayers?.forEach{ .removeFromSuperlayer()}