web-dev-qa-db-ja.com

すべてのサブビューを削除しますか?

私のアプリがそのルートView Controllerに戻ったら、viewDidAppear:メソッドですべてのサブビューを削除する必要があります。

これどうやってするの?

307

編集:おかげで cocoafan :この状況はNSViewUIViewの扱いが異なることで混乱しています。 NSView(デスクトップMac開発のみ)の場合は、単純に以下を使用できます。

[someNSView setSubviews:[NSArray array]];

UIView(iOS開発のみ)の場合、subviewsプロパティがサブビューの配列のコピーを返すため、makeObjectsPerformSelector:を安全に使用できます。

[[someUIView subviews]
 makeObjectsPerformSelector:@selector(removeFromSuperview)];

Tommy 列挙中にmakeObjectsPerformSelector:subviews配列を変更しているように見えることを指摘していただきありがとうございます(これはNSViewに対しては行われますが、UIViewに対しては行われません)。

詳しくは this SO question をご覧ください。

注:これら2つの方法のいずれかを使用すると、メインビューに含まれるすべてのビューが削除され、解放されます。他に保存されていない場合 removeFromSuperview についてのAppleのドキュメントから:

受信者のスーパービューがゼロでない場合、このメソッドは受信者を解放します。ビューを再利用する予定の場合は、このメソッドを呼び出す前に必ずビューを保持し、それを使い終わったとき、または別のビュー階層に追加した後は、適切に解放してください。

563
e.James

ルートコントローラからすべてのサブビューを取得し、それぞれにremoveFromSuperviewを送信します。

NSArray *viewsToRemove = [self.view subviews];
for (UIView *v in viewsToRemove) {
    [v removeFromSuperview];
}
170

Swiftでは、次のように機能的アプローチを使うことができます。

view.subviews.forEach { $0.removeFromSuperview() }

比較として、命令型アプローチは次のようになります。

for subview in view.subviews {
    subview.removeFromSuperview()
}

これらのコードスニペットはiOS/tvOSでしか動作しませんが、macOSでは状況が少し異なります。

106
Dschee

あなたのUIView(ここではyourView)のすべてのサブビューを削除したい場合は、あなたのボタンをクリックしてこのコードを書いてください:

[[yourView subviews] makeObjectsPerformSelector: @selector(removeFromSuperview)];
13
Mohd Rahib

iOSでは配列のコピーが保存されているので、これはOSXにのみ適用されます

すべてのサブビューを削除するときは、配列の末尾から削除を開始し、最初に達するまで削除を続けることをお勧めします。これは、次の2行のコードで実現できます。

for (int i=mySuperView.subviews.count-1; i>=0; i--)
        [[mySuperView.subviews objectAtIndex:i] removeFromSuperview];

Swift 1.2

for var i=mySuperView.subviews.count-1; i>=0; i-- {
    mySuperView.subviews[i].removeFromSuperview();
}

または(効率は悪くなりますが読みやすくなります)

for subview in mySuperView.subviews.reverse() {
    subview.removeFromSuperview()
}

NOTE

removeFromSuperviewメッセージが配列のすべてのオブジェクトに送信される前にUIViewインスタンスが削除されるとクラッシュする可能性があるため、NOTサブビューを通常の順序で削除する必要があります。 (明らかに、最後の要素を削除してもクラッシュは起こりません)

したがって、コードは

[[someUIView subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];

NOTを使うべきです。

makeObjectsPerformSelectorに関するAppleのドキュメント からの引用:

最初のオブジェクトから始めて配列を通って最後のオブジェクトまで、指定されたセレクタで識別されるメッセージを配列内の各オブジェクトに送信します。

(これはこの目的のための間違った方向でしょう)

8
Daniel

この方法を試してみてくださいSwift 2.0

view.subviews.forEach { $0.removeFromSuperview() }
4
William Hu

以下のコードを使用して、すべてのサブビューを削除します。

for (UIView *view in [self.view subviews]) 
{
 [view removeFromSuperview];
}
4

Swift UIView拡張子を使う:

extension UIView {
    func removeAllSubviews() {
        for subview in subviews {
            subview.removeFromSuperview()
        }
    }
}
2
mixel

Swiftを使用している場合は、次のように簡単です。

subviews.map { $0.removeFromSuperview }

哲学的にはmakeObjectsPerformSelectorのアプローチと似ていますが、もう少し型安全性があります。

2
lms

Objective-Cでは、UIViewクラスからカテゴリメソッドを作成して先に進みます。

- (void)removeAllSubviews
{
    for (UIView *subview in self.subviews)
        [subview removeFromSuperview];
}
2
Rickster
view.subviews.forEach { $0.removeFromSuperview() }
1
MAGiGO

すべてのサブビューを削除するには

- (void)makeObjectsPerformSelector:(SEL)aSelector;

使用法 :

[self.View.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];

このメソッドはNSArray.hファイルにあり、NSArray(NSExtendedArray)インタフェースを使用します。

1

Monotouch/xamarin.iosでこれは私のために働きました:

SomeParentUiView.Subviews.All(x => x.RemoveFromSuperview);
0
Daniele D.

自動レイアウトを使用しているios 6では、制約も削除するために少しコードを追加する必要がありました。

NSMutableArray * constraints_to_remove = [ @[] mutableCopy] ;
for( NSLayoutConstraint * constraint in tagview.constraints) {
    if( [tagview.subviews containsObject:constraint.firstItem] ||
       [tagview.subviews containsObject:constraint.secondItem] ) {
        [constraints_to_remove addObject:constraint];
    }
}
[tagview removeConstraints:constraints_to_remove];

[ [tagview subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];

私はこれを行うためのより良い方法があると確信していますが、それは私のために働いた。私の場合は、XCodeに制約が設定されているため、直接の[tagview removeConstraints:tagview.constraints]を使用できませんでした。

0