Verifique se uma subvisualização está em uma visão

97

Estou fazendo um aplicativo onde adiciono uma subvisão a uma visão usando addSubview:em um IBAction. Da mesma forma, quando o botão com isso IBActionfor tocado novamente, deve-se chamar removeFromSuperviewaquela subvisualização adicionada a IBAction:

PSEUDO-CÓDIGO

-(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
fonte

Respostas:

271

Você provavelmente está procurando por UIView's -(BOOL)isDescendantOfView:(UIView *)view;tomadas na referência de classe UIView .

Valor de retorno SIM se o receptor for uma subvisão imediata ou distante da visão ou se a visão for o próprio receptor; caso contrário, NÃO.

Você vai acabar com um código como:

Objective-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()
    }
}
palma
fonte
2
Não funciona, apenas adiciona a visão sobre ele. Vou editar o código para mostrar o caso real
pmerino
@ zad0xsis - Não entendo o caso real. Se você adicionou a segunda visualização usando o addSubview:método (o que provavelmente é o caso da primeira vez), na próxima vez, você alcançará a parte else, porque a segunda visualização agora é uma subvisão da primeira. Não é o que você estava tentando fazer? Você está procurando outro mecanismo como prensent um view controller modalmente?
bem, popoverViewé uma subvisão de rootView (rootViewController). Quero verificar se está na tela (se tem rootView como superview) e se tiver, remova-o ou então adicione-o se não
estiver
está [self popoverView]retornando um popover recém-criado a cada vez? não pode adicionar uma visão "sobre ela" se for a mesma visão, adicionando uma visão que já existe em um ambiente autônomo. se o popoverViewmétodo estiver criando um novo a cada vez, ele sempre não estará na hierarquia de visualização
bshirley
1
Uma consideração importante que me fez tropeçar aqui: ao remover e adicionar subvisualizações que você está segurando com as propriedades IBOutlet (ou ivars), você precisa se certificar de que as propriedades (ivars) são fortes , ou que (pré ARC) estão retidas . Por padrão, se você pressionar o botão Ctrl e arrastar de uma visualização para um controlador para criar uma saída, será criada como fraca, pois assume que a visualização criada na ponta a possuirá, portanto, você não precisa de uma referência forte. Mas se você removê-lo programaticamente, ele desalocará o controle e definirá sua referência como nil (em ARC).
Ruibarbo
18

Experimente isto:

-(IBAction)showPopup:(id)sender
{
    if (!myView.superview)
        [self.view addSubview:myView];
    else
        [myView removeFromSuperview];
}
Mark Granoff
fonte
impressionante! às vezes ele precisa de myView.view.superview, mas funcionou como mágica para mim. Obrigado @MarkGranoff
Lior Frenkel
11
    UIView *subview = ...;
    if([self.view.subviews containsObject:subview]) {
        ...
    }
Michael Frederick
fonte
Não funciona, apenas adiciona a visão sobre ele. Vou editar o código para mostrar o caso real - zad0xsis 1 min atrás editar
pmerino
12
@pmerino Parabéns por ser tão preguiçoso que você também copiou "zad0xsis 1 min atrás edit" :-)
Thomas Kekeisen
Acho que isso é mais caro do que as outras soluções, para ser honesto, porque tem que iterar em todas as
subvisualizações
4

O equivalente do Swift será mais ou menos assim:

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

Verifique a visão geral da subvisualização ...

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

Sua condição if deve ser como

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

}
Saran
fonte
Esta é uma ligeira modificação da resposta de Michael Frederick. Ele dá resultados diferentes do código de Vincent que usa isDescendantOfView:?
paulmelnikow de
Isso absolutamente produz um resultado diferente. Isso só verifica se é uma visualização de criança, não de um neto ou bisneto, etc.
Sami Samhuri
0

Aqui usamos duas visualizações diferentes. A visão pai é aquela na qual procuramos a visão descendente e verificamos se foi adicionada à visão pai ou não.

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