Controlla se una vista secondaria è in una vista


97

Sto creando un'app in cui aggiungo una vista secondaria a una vista utilizzando addSubview:su un file IBAction. Allo stesso modo, quando il pulsante con quello IBActionviene toccato di nuovo dovrebbe chiamare removeFromSuperviewquella sottoview aggiunta su quella IBAction:

CODICE 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];
    }

}

Risposte:


271

Probabilmente stai cercando UIView -(BOOL)isDescendantOfView:(UIView *)view;nel riferimento alla classe UIView .

Valore restituito YES se il destinatario è una vista secondaria immediata o distante o se la vista è il destinatario stesso; altrimenti NO.

Ti ritroverai con un codice come:

Obiettivo-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()
    }
}

2
Non funziona, aggiunge solo la vista su di esso.
Modificherò

@ zad0xsis - Non capisco il caso reale. Se hai aggiunto la seconda vista utilizzando il addSubview:metodo (che è probabilmente il caso della prima volta), la prossima volta raggiungerai la parte else perché la seconda vista ora è una sottoview della prima. Non è quello che stavi cercando di fare? Stai forse cercando un altro meccanismo come il prensenting modale di un controller di visualizzazione?

beh, popoverViewè una sottoview di rootView (rootViewController). Voglio controllare se è sullo schermo (se ha rootView come superview) e in tal caso rimuoverlo o aggiungerlo se non lo è
pmerino

è [self popoverView]la restituzione di un appena creato popover ogni volta? non può aggiungere una vista "sopra di essa" se è la stessa vista, l'aggiunta di una vista che è già presente è un divieto. se il popoverViewmetodo ne crea uno nuovo ogni volta, non sarà sempre nella gerarchia di visualizzazione
bshirley

1
Una considerazione importante che mi ha fatto inciampare qui: quando rimuovi e aggiungi sottoview a cui ti stai aggrappando con le proprietà IBOutlet (o ivars) devi assicurarti che le proprietà (ivars) siano forti o che (pre ARC) vengano mantenute . Per impostazione predefinita, se si trascina ctrl-trascina da una vista a un controller per creare una presa, verrà creata come debole perché si presume che la vista creata nel pennino la possieda, quindi non è necessario un riferimento forte. Ma se lo rimuovi a livello di programmazione, rillocerà il controllo e imposterà il tuo riferimento su zero (in ARC).
Rabarbaro

18

Prova questo:

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

eccezionale! a volte ha bisogno di myView.view.superview, ma ha funzionato come per magia per me. Grazie @MarkGranoff
Lior Frenkel

11
    UIView *subview = ...;
    if([self.view.subviews containsObject:subview]) {
        ...
    }

Non funziona, aggiunge solo la vista su di esso. Modificherò il codice per mostrare il caso reale - zad0xsis 1 minuto fa modifica
pmerino

12
@pmerino Congratulazioni per essere così pigro che hai anche copiato "zad0xsis 1 min ago edit" :-)
Thomas Kekeisen

Penso che questo sia più costoso delle altre soluzioni ad essere onesti perché deve iterare attraverso tutte le sottoview
SimplyKiwi

4

L'equivalente Swift avrà un aspetto simile a questo:

if(!myView.isDescendantOfView(self.view)) {
    self.view.addSubview(myView)
} else {
    myView.removeFromSuperview()
}

2

Controlla la superview della sottoview ...

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

1

La tua condizione if dovrebbe andare come

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

}

Questa è una leggera modifica della risposta di Michael Frederick. Fornisce risultati diversi dal codice di Vincent che utilizza isDescendantOfView:?
paulmelnikow

Produce assolutamente un risultato diverso. Questo controlla solo se si tratta di una vista di un bambino, non di un nipote o pronipote, ecc.
Sami Samhuri

0

Qui abbiamo usato due diverse visualizzazioni. La vista genitore è la vista in cui cerchiamo la vista discendente e controlliamo se aggiunta o meno alla vista genitore.

if parentView.subviews.contains(descendantView) {
   // descendant view added to the parent view.
}else{
  // descendant view not added to the parent view.
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.