Lorsque mon application revient à son contrôleur de vue racine, dans la méthode viewDidAppear:
, je dois supprimer toutes les sous-vues.
Comment puis-je faire ceci?
Edit: Merci à cocoafan : Cette situation est embrouillée par le fait que NSView
et UIView
gérer les choses différemment. Pour NSView
(développement Mac de bureau uniquement), vous pouvez simplement utiliser les éléments suivants:
[someNSView setSubviews:[NSArray array]];
Pour UIView
(développement iOS uniquement), vous pouvez utiliser en toute sécurité makeObjectsPerformSelector:
car la propriété subviews
renvoie une copie du tableau de sous-vues. :
[[someUIView subviews]
makeObjectsPerformSelector:@selector(removeFromSuperview)];
Merci à Tommy pour avoir signalé que makeObjectsPerformSelector:
semble modifier le tableau subviews
pendant son énumération (ce qui est le cas pour NSView
, mais pas pour UIView
).
Veuillez consulter this SO question pour plus de détails.
Remarque: L'utilisation de l'une de ces deux méthodes supprimera toutes les vues contenues dans votre vue principale et les libérera . , s’ils ne sont pas conservés ailleurs. D'après la documentation d'Apple sur removeFromSuperview :
Si la vue du récepteur n’est pas nulle, cette méthode le libère. Si vous envisagez de réutiliser la vue, veillez à la conserver avant d'appeler cette méthode et veillez à la publier comme il convient lorsque vous avez terminé ou après l'avoir ajoutée à une autre hiérarchie de vues.
Obtenez toutes les sous-vues de votre contrôleur racine et envoyez à chacune un removeFromSuperview:
NSArray *viewsToRemove = [self.view subviews];
for (UIView *v in viewsToRemove) {
[v removeFromSuperview];
}
Dans Swift, vous pouvez utiliser une approche fonctionnelle comme ceci:
view.subviews.forEach { $0.removeFromSuperview() }
À titre de comparaison, le approche impérative ressemblerait à ceci:
for subview in view.subviews {
subview.removeFromSuperview()
}
Ces extraits de code ne fonctionnent que dans iOS/tvOS bien que les choses soient un peu différentes sur macOS.
Si vous souhaitez supprimer toutes les sous-vues de votre UIView (ici yourView
), écrivez ce code en cliquant sur le bouton:
[[yourView subviews] makeObjectsPerformSelector: @selector(removeFromSuperview)];
Ceci ne s'applique qu'à OSX car dans iOS une copie du tableau est conservée
Lorsque vous supprimez toutes les sous-vues, il est judicieux de commencer par supprimer à la fin du tableau et de poursuivre la suppression jusqu'au début. Ceci peut être accompli avec ces deux lignes de code:
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();
}
ou (moins efficace, mais plus lisible)
for subview in mySuperView.subviews.reverse() {
subview.removeFromSuperview()
}
NOTE
Vous devez PAS supprimer les vues secondaires dans l'ordre normal, car cela peut provoquer un blocage si une instance de UIView est supprimée avant le message removeFromSuperview
a été envoyé à tous les objets du tableau. (Evidemment, la suppression du dernier élément ne provoquerait pas de crash)
Par conséquent, le code
[[someUIView subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
devrait PAS être utilisé.
Citation de documentation Apple sur makeObjectsPerformSelector :
Envoie à chaque objet du tableau le message identifié par un sélecteur donné, en commençant par le premier objet et en poursuivant dans le tableau jusqu'au dernier objet.
(quelle serait la mauvaise direction à cette fin)
Essayez de cette façon Swift 2.0
view.subviews.forEach { $0.removeFromSuperview() }
Utilisez le code suivant pour supprimer toutes les sous-vues.
for (UIView *view in [self.view subviews])
{
[view removeFromSuperview];
}
Utilisation de l'extension Swift UIView
:
extension UIView {
func removeAllSubviews() {
for subview in subviews {
subview.removeFromSuperview()
}
}
}
Si vous utilisez Swift, c'est aussi simple que:
subviews.map { $0.removeFromSuperview }
Sa philosophie est similaire à celle de la méthode makeObjectsPerformSelector
, mais avec un peu plus de sécurité.
Dans objectif-C, créez une méthode de catégorie à partir de la classe UIView.
- (void)removeAllSubviews
{
for (UIView *subview in self.subviews)
[subview removeFromSuperview];
}
view.subviews.forEach { $0.removeFromSuperview() }
Afin de supprimer toutes les vues secondaires Syntaxe:
- (void)makeObjectsPerformSelector:(SEL)aSelector;
Utilisation:
[self.View.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
Cette méthode est présente dans le fichier NSArray.h et utilise l'interface NSArray (NSExtendedArray).
Dans monotouch/xamarin.ios cela a fonctionné pour moi:
SomeParentUiView.Subviews.All(x => x.RemoveFromSuperview);
Pour iOS6 utilisant autolayout je devais ajouter un peu de code pour supprimer les contraintes aussi.
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)];
Je suis sûr qu'il y a une manière plus ordonnée de faire cela, mais cela a fonctionné pour moi. Dans mon cas, je ne pouvais pas utiliser de code [tagview removeConstraints:tagview.constraints]
direct car certaines contraintes définies dans XCode étaient effacées.