Compruebe si una subvista está en una vista

97

Estoy creando una aplicación donde agrego una subvista a una vista usando addSubview:en un IBAction. De la misma manera, cuando el botón con eso IBActionse toca nuevamente, se debe llamar removeFromSuperviewa esa subvista agregada en eso IBAction:

CÓDIGO 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
fuente

Respuestas:

271

Probablemente esté buscando la referencia de clase UIView-(BOOL)isDescendantOfView:(UIView *)view; tomada en UIView .

Valor de retorno SÍ si el receptor es una subvista de vista inmediata o distante o si la vista es el propio receptor; De otra manera no.

Terminarás con un código como:

C objetivo

- (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
fuente
2
No funciona, solo agrega la vista sobre él.
Editaré
@ zad0xsis - No entiendo el caso real. Si agregó la segunda vista usando el addSubview:método (que probablemente sea el caso la primera vez), la próxima vez, llegará a la parte else porque la segunda vista ahora es una subvista de la primera. ¿No es lo que estabas intentando hacer? ¿Quizás esté buscando otro mecanismo como presentar un controlador de vista de forma modal?
bueno, popoverViewes una subvista de rootView (rootViewController). Quiero verificar si está en la pantalla (si tiene rootView como supervista) y si es así, elimínelo o agréguelo si no lo está
pmerino
está [self popoverView]devolviendo un popover recién creado cada vez? no puede agregar una vista "sobre ella" si es la misma vista, agregando una vista que ya no existe. si el popoverViewmétodo crea uno nuevo cada vez, entonces no siempre estará en la jerarquía de vista
bshirley
1
Una consideración importante que me hizo tropezar aquí: al eliminar y luego agregar subvistas a las que se aferra con las propiedades de IBOutlet (o ivars), debe asegurarse de que las propiedades (ivars) sean fuertes , o que (pre ARC) se conserven . De forma predeterminada, si ctrl-arrastra desde una vista a un controlador para crear una salida, la creará como débil porque asume que la vista creada en la plumilla la poseerá, por lo que no necesita una referencia sólida. Pero si lo elimina mediante programación, desasignará el control y establecerá su referencia en nil (en ARC).
Ruibarbo
18

Prueba esto:

-(IBAction)showPopup:(id)sender
{
    if (!myView.superview)
        [self.view addSubview:myView];
    else
        [myView removeFromSuperview];
}
Mark Granoff
fuente
¡increíble! a veces necesita myView.view.superview, pero funcionó como magia para mí. Gracias @MarkGranoff
Lior Frenkel
11
    UIView *subview = ...;
    if([self.view.subviews containsObject:subview]) {
        ...
    }
Michael Frederick
fuente
No funciona, solo agrega la vista sobre él. Editaré el código para mostrar el caso real - zad0xsis hace 1 minuto editar
pmerino
12
@pmerino Felicidades por ser tan vago que también copió "zad0xsis hace 1 minuto editar" :-)
Thomas Kekeisen
Creo que esto es más caro que las otras soluciones para ser honesto porque tiene que iterar a través de todas las subvistas
SimplyKiwi
4

El equivalente de Swift se verá así:

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

Compruebe la supervista de la subvista ...

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

Tu condición debería ir como

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

}
Saran
fuente
Esta es una ligera modificación de la respuesta de Michael Frederick. ¿Da resultados diferentes del código de Vincent que usa isDescendantOfView:?
paulmelnikow
Absolutamente produce un resultado diferente. Esto solo verifica si es una vista de niño, no un nieto o bisnieto, etc.
Sami Samhuri
0

Aquí usamos dos vistas diferentes. La vista principal es la vista en la que estamos buscando la vista descendiente y verificamos si se agregó a la vista principal o no.

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