删除所有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 = @[];