删除所有CALayer的子层

我在删除图层的所有子图层时遇到了问题。 我目前手动执行此操作,但会带来不必要的混乱。 我在google上发现了很多这方面的话题,但是没有答案。

我试图做这样的事情:

用于(rootLayer.sublayers中的CALayer *图层)
 {
     [layer removeFromSublayer];
 }

但它没有工作。

此外,我试图将rootLayer.sublayers克隆到单独的NSArray,但结果是相同的。

有任何想法吗?

编辑:

我认为现在可行,但我错了。 它适用于CALayers,但它不适用于CATextLayers。 有任何想法吗?

删除图层中所有子图层的最简单方法是将子图层属性设置为nil:

rootLayer.sublayers = nil;

以下应该工作:

 for (CALayer *layer in [[rootLayer.sublayers copy] autorelease]) { [layer removeFromSuperlayer]; } 
 [rootLayer.sublayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)]; 

Swift(短版):

layer.sublayers?.forEach { $0.removeFromSuperlayer() }

调用rootLayer.sublayers = nil; 可能会导致崩溃(例如,如果在iOS 8下,您在拥有rootLayer的视图上调用removeFromSuperview两次)。

正确的做法应该是:

[[rootLayer.sublayers copy] makeObjectsPerformSelector:@selector(removeFromSuperlayer)]

copy的调用是需要的,以便迭代调用removeFromSuperlayer的数组不会被修改,否则会引发exception。

如何使用反向枚举?

 NSEnumerator *enumerator = [rootLayer.sublayers reverseObjectEnumerator]; for(CALayer *layer in enumerator) { [layer removeFromSuperlayer]; } 

因为子层中的组在枚举过程中发生更改,如果顺序正常。 我想知道上面的代码的结果。

不分青红皂白地删除所有子层会导致iOS 7中令人讨厌的崩溃,这可能会在程序执行后期发生。 我已经使用rootLayer.sublayers = nil[rootLayer.sublayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)]彻底地testing了这一点。 必须有一个系统创build的图层越来越混乱。

你必须保留你自己的一系列图层,并自己删除它们:

 [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#中执行此操作。 我有一个与一些CAShapeLayers边界的UITableViewCell 。 所有上述选项(包括复制数组,然后删除图层导致崩溃)。 为我工作的方法:

当添加CALayer ,我给了它一个名字:

  var border = new CALayer(); border.BackgroundColor = color.CGColor; border.Frame = new CGRect(x, y, width, height); border.Name = "borderLayerName"; Layer.AddSublayer(border); 

UITableViewCell PrepareForReuse ,我创build了一个SubLayers属性的副本,并删除了与我之前分配的名称相匹配的任何内容:

  CALayer[] copy = new CALayer[Layer.Sublayers.Length]; Layer.Sublayers.CopyTo(copy, 0); copy.FirstOrDefault(l => l.Name == "borderLayerName")?.RemoveFromSuperLayer(); 

没有崩溃。

希望这可以帮助!

如果UIView包含任何子视图,则设置self.view.layer.sublayers = nil[layer removeFromSuperlayer]将导致崩溃。 从superLayer中移除CALayer最好方法是维护一个图层的数组。 例如,该数组是arrayOfLayers,

每次你在UIView.sublayer上添加一个图层,在这个数组中添加这个图层。 [

 arrayOfLayers addObject:layer]; [self.view.layer addSublayer:layer]; 

虽然删除只是调用这个,

 [arrayOfLayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)]; 

我面临同样的问题,并find许多解决scheme,但没有一个是完美的。
最后从pnavk的答案我得到了主意。 在那里的代码是Xamarin / C#用户。
iOS版本可能如下:

Swift 2.3

  if rootLayer.sublayers?.count > 0 { rootLayer.sublayers?.forEach { if $0.name == "bottomBorderLayer" { $0.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 

Objective-C的

 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循环来检查是否已经应用了任何边框?
要确定以前添加的边界,我使用CALayer的名称属性。 并且在从子层移除之前比较该层。
在使用name属性之前,我已经尝试了相同的代码,但是它会造成随机崩溃。 但是在使用名称属性和比较名称之前删除将解决崩溃问题。

我希望这会帮助别人。

当然你可以这样做:
self.layer.sublayers=nil;
如Pascal Bourque所build议的那样。 但是最好给setter调用sublayers属性:
[self.layer setSublayers:nil];
为了避免任何清理问题,如果可能的话。

对于swift3 +,你可以使用这个。

yourView.layer.sublayers?.removeAll(keepingCapacity: true)

请参阅: Apple API参考

或者你可以: yourView.layer.sublayers?.forEach{ $0.removeFromSuperlayer()}

那么做什么:

 rootLayer.sublayers = @[];