私のアプリがそのルートView Controllerに戻ったら、viewDidAppear:
メソッドですべてのサブビューを削除する必要があります。
これどうやってするの?
編集:おかげで cocoafan :この状況はNSView
とUIView
の扱いが異なることで混乱しています。 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のドキュメントから:
受信者のスーパービューがゼロでない場合、このメソッドは受信者を解放します。ビューを再利用する予定の場合は、このメソッドを呼び出す前に必ずビューを保持し、それを使い終わったとき、または別のビュー階層に追加した後は、適切に解放してください。
ルートコントローラからすべてのサブビューを取得し、それぞれにremoveFromSuperviewを送信します。
NSArray *viewsToRemove = [self.view subviews];
for (UIView *v in viewsToRemove) {
[v removeFromSuperview];
}
Swiftでは、次のように機能的アプローチを使うことができます。
view.subviews.forEach { $0.removeFromSuperview() }
比較として、命令型アプローチは次のようになります。
for subview in view.subviews {
subview.removeFromSuperview()
}
これらのコードスニペットはiOS/tvOSでしか動作しませんが、macOSでは状況が少し異なります。
あなたのUIView(ここではyourView
)のすべてのサブビューを削除したい場合は、あなたのボタンをクリックしてこのコードを書いてください:
[[yourView subviews] makeObjectsPerformSelector: @selector(removeFromSuperview)];
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のドキュメント からの引用:
最初のオブジェクトから始めて配列を通って最後のオブジェクトまで、指定されたセレクタで識別されるメッセージを配列内の各オブジェクトに送信します。
(これはこの目的のための間違った方向でしょう)
この方法を試してみてくださいSwift 2.0
view.subviews.forEach { $0.removeFromSuperview() }
以下のコードを使用して、すべてのサブビューを削除します。
for (UIView *view in [self.view subviews])
{
[view removeFromSuperview];
}
Swift UIView
拡張子を使う:
extension UIView {
func removeAllSubviews() {
for subview in subviews {
subview.removeFromSuperview()
}
}
}
Swiftを使用している場合は、次のように簡単です。
subviews.map { $0.removeFromSuperview }
哲学的にはmakeObjectsPerformSelector
のアプローチと似ていますが、もう少し型安全性があります。
Objective-Cでは、UIViewクラスからカテゴリメソッドを作成して先に進みます。
- (void)removeAllSubviews
{
for (UIView *subview in self.subviews)
[subview removeFromSuperview];
}
view.subviews.forEach { $0.removeFromSuperview() }
すべてのサブビューを削除するには
- (void)makeObjectsPerformSelector:(SEL)aSelector;
使用法 :
[self.View.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
このメソッドはNSArray.hファイルにあり、NSArray(NSExtendedArray)インタフェースを使用します。
Monotouch/xamarin.iosでこれは私のために働きました:
SomeParentUiView.Subviews.All(x => x.RemoveFromSuperview);
自動レイアウトを使用している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]
を使用できませんでした。