在做動(dòng)畫時(shí)候榕订,往往需要在當(dāng)前CALayer中添加許多子圖層(subLayers),當(dāng)動(dòng)畫完成后,需要將這些subLayers從當(dāng)前的CALayer中移除,加入我需要移除當(dāng)前CALayer中類型為CAShapeLayer的subLayers,通常我們會(huì)采用這種做法:
NSArray<CALayer *> *subLayers = self.layer.sublayers;
[subLayers enumerateObjectsUsingBlock:^(CALayer * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if([obj isKindOfClass:[CAShapeLayer class]]){
[obj removeFromSuperlayer];
}
}];
然而尉桩,這時(shí)候會(huì)出現(xiàn)crash,具體錯(cuò)誤堆棧信息如下:
可以看到修改不變的Array導(dǎo)致的。也就是說CALayer的subLayers是不變的數(shù)組贪庙。推測是因?yàn)閞emoveFromSuperlayer會(huì)修改self.layer.sublayers,而此時(shí)self.layer.sublayers調(diào)用了enumerateObjectsUsingBlock函數(shù)蜘犁,也就是在遍歷的時(shí)候出現(xiàn)了修改,所以會(huì)出現(xiàn)crash插勤。
網(wǎng)上有一種解決方案是:
[self.layer.sublayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)];
但是我需要移除部分的subLayers時(shí)候就需要另想其他辦法了沽瘦。其實(shí)這里很簡單就是將self.layer.sublayers數(shù)組中的需要?jiǎng)h除的子Layer選擇出來,存儲到另一個(gè)數(shù)組中农尖,然后在進(jìn)行刪除析恋,這時(shí)候不會(huì)出現(xiàn)crash。
代碼如下:
NSArray<CALayer *> *subLayers = self.layer.sublayers;
NSArray<CALayer *> *removedLayers = [subLayers filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
return [evaluatedObject isKindOfClass:[CAShapeLayer class]];
}]];
[removedLayers enumerateObjectsUsingBlock:^(CALayer * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[obj removeFromSuperlayer];
}];
是不是很easy盛卡,??