レイヤーのサブレイヤーをすべて削除するのに問題があります。私は現在これを手動で行っていますが、それは不必要な混乱をもたらします。私はグーグルでこれに関する多くのトピックを見つけましたが、答えはありません。
私はこのようなことをしようとしました:
for(CALayer * rootLayer.sublayersのレイヤー) { [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を2回呼び出す場合)。
正しい方法は次のとおりです。
[[rootLayer.sublayers copy] makeObjectsPerformSelector:@selector(removeFromSuperlayer)]
copy
が繰り返し呼び出される配列が変更されないように、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)];
すべてのサブレイヤーを無差別に削除すると、iOS 7で厄介なクラッシュが発生し、プログラムの実行のずっと後に発生する可能性があります。 _rootLayer.sublayers = nil
_と[rootLayer.sublayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)]
の両方を使用して、これを徹底的にテストしました。システムが作成したレイヤーが台無しになっている必要があります。
独自のレイヤーの配列を保持し、自分で削除する必要があります。
_[myArrayOfLayersIAddedMyself makeObjectsPerformSelector:@selector(removeFromSuperlayer)];
_
逆列挙を使用してはどうですか?
NSEnumerator *enumerator = [rootLayer.sublayers reverseObjectEnumerator];
for(CALayer *layer in enumerator) {
[layer removeFromSuperlayer];
}
順序が正常であれば、サブレイヤーのグループは列挙中に変更されるためです。上記のコードの結果を知りたいです。
インデックス0の最初のサブレイヤーだけを削除しようとしましたが、これは機能しました。
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if ([cell.contentView.layer.sublayers count] != 0) {
[[cell.contentView.layer.sublayers objectAtIndex:0] removeFromSuperlayer];
}
私は同じ問題に直面し、多くの解決策を見つけましたが、どれも完璧ではありません。
最後に 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プロパティを使用します。そして、サブレイヤーから削除する前にそのレイヤーを比較します。
nameプロパティを使用する前に同じコードを試しましたが、ランダムにクラッシュします。ただし、nameプロパティを使用し、削除する前に名前を比較すると、クラッシュの問題は解決します。
これが誰かの助けになることを願っています。
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();
クラッシュしません。
お役に立てれば!