Vérifier si une sous-vue est dans une vue

97

Je fais une application où j'ajoute un sous - vue à une vue à l' aide addSubview:sur un IBAction. De la même manière, lorsque le bouton avec qui IBActionest touché à nouveau doit appeler removeFromSuperviewcette sous-vue ajoutée à cela IBAction:

CODE PSEUDO

-(IBAction)showPopup:(id)sender 
{
    System_monitorAppDelegate *delegate = (System_monitorAppDelegate *)[[UIApplication sharedApplication] delegate];
    UIView *rootView = delegate.window.rootViewController.view;

    if([self popoverView] is not on rootView) 
    { 
        [rootView addSubview:[self popoverView]];
    } 
    else 
    {
        [[self popoverView] removeFromSuperview];
    }

}
pmerino
la source

Réponses:

271

Vous recherchez probablement des UIView -(BOOL)isDescendantOfView:(UIView *)view;prises dans la référence de classe UIView .

Valeur de retour OUI si le récepteur est une vue secondaire immédiate ou distante de la vue ou si la vue est le récepteur lui-même; sinon NON.

Vous vous retrouverez avec un code comme:

Objectif c

- (IBAction)showPopup:(id)sender {
    if(![self.myView isDescendantOfView:self.view]) { 
        [self.view addSubview:self.myView];
    } else {
        [self.myView removeFromSuperview];
    }
}

Swift 3

@IBAction func showPopup(sender: AnyObject) {
    if !self.myView.isDescendant(of: self.view) {
        self.view.addSubview(self.myView)
    } else {
        self.myView.removeFromSuperview()
    }
}
palme
la source
2
Cela ne fonctionne pas, ajoute simplement la vue dessus. Je vais modifier le code pour montrer le cas réel
pmerino
@ zad0xsis - Je ne comprends pas le cas réel. Si vous avez ajouté la deuxième vue à l'aide de la addSubview:méthode (ce qui est probablement le cas la première fois), la prochaine fois, vous atteindrez la partie else car la deuxième vue est maintenant une sous-vue de la première. N'est-ce pas ce que vous essayiez de faire? Vous recherchez peut-être un autre mécanisme comme la présentation d'un contrôleur de vue de manière modale?
bien, popoverViewest une sous-vue de rootView (rootViewController). Je veux vérifier s'il est à l'écran (s'il a rootView comme superview) et si c'est le cas, supprimez-le ou ajoutez-le si ce n'est pas le cas
pmerino
est [self popoverView]renvoie une nouvelle popover à chaque fois? il ne peut pas ajouter une vue "dessus" s'il s'agit de la même vue, en ajoutant une vue qui existe déjà est interdite. si la popoverViewméthode en crée une nouvelle à chaque fois, elle ne sera toujours pas dans la hiérarchie des vues
bshirley
1
Une considération importante qui m'a trébuché ici: lors de la suppression, puis de l'ajout de sous-vues que vous conservez avec les propriétés IBOutlet (ou ivars), vous devez vous assurer que les propriétés (ivars) sont fortes. , ou que (avant ARC) elles sont conservées . Par défaut, si vous ctrl-faites glisser d'une vue vers un contrôleur pour créer une prise, cela la créera comme faible car elle suppose que la vue créée dans la pointe en sera propriétaire, vous n'avez donc pas besoin d'une référence forte. Mais si vous le supprimez ensuite par programme, il désallouera le contrôle et définira votre référence sur nil (dans ARC).
Rhubarb
18

Essaye ça:

-(IBAction)showPopup:(id)sender
{
    if (!myView.superview)
        [self.view addSubview:myView];
    else
        [myView removeFromSuperview];
}
Mark Granoff
la source
impressionnant! parfois, il a besoin de myView.view.superview, mais cela a fonctionné comme par magie pour moi. Merci @MarkGranoff
Lior Frenkel
11
    UIView *subview = ...;
    if([self.view.subviews containsObject:subview]) {
        ...
    }
Michael Frederick
la source
Cela ne fonctionne pas, ajoute simplement la vue dessus. Je vais éditer le code pour montrer le cas réel - zad0xsis il y a 1 min modifier
pmerino
12
@pmerino Félicitations pour être aussi paresseux que vous avez également copié "zad0xsis il y a 1 min edit" :-)
Thomas Kekeisen
Je pense que c'est plus cher que les autres solutions pour être honnête car il doit parcourir toutes les sous
vues SimplyKiwi
4

L'équivalent Swift ressemblera à ceci:

if(!myView.isDescendantOfView(self.view)) {
    self.view.addSubview(myView)
} else {
    myView.removeFromSuperview()
}
JaySH
la source
2

Vérifiez la vue de la sous-vue ...

-(IBAction)showPopup:(id)sender {
    if([[self myView] superview] == self.view) { 
        [[self myView] removeFromSuperview];           
    } else {
        [self.view addSubview:[self myView]];         
    }
}
Jason Harwig
la source
1

Votre condition si devrait aller comme

if (!([rootView subviews] containsObject:[self popoverView])) { 
    [rootView addSubview:[self popoverView]];
} else {
    [[self popoverView] removeFromSuperview];

}
Saran
la source
C'est une légère modification de la réponse de Michael Frederick. Donne-t-il des résultats différents du code de Vincent qui utilise isDescendantOfView:?
paulmelnikow
Cela donne absolument un résultat différent. Cela vérifie uniquement s'il s'agit d'une vue enfant, pas d'un petit-enfant ou d'un arrière-petit-enfant, etc.
Sami Samhuri
0

Ici, nous avons utilisé deux vues différentes. La vue parent est la vue dans laquelle nous recherchons la vue descendante et vérifions si elle est ajoutée à la vue parent ou non.

if parentView.subviews.contains(descendantView) {
   // descendant view added to the parent view.
}else{
  // descendant view not added to the parent view.
}
Shubham
la source