Sprawdź, czy widok podrzędny jest w widoku


97

Tworzę aplikację, w której dodaję podwidok do widoku za addSubview:pomocą IBAction. W ten sam sposób, gdy przycisk z tymIBAction zostanie ponownie dotknięty, powinien wywołać removeFromSuperviewten widok podrzędny dodany do tego IBAction:

PSEUDO KOD

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

}

Odpowiedzi:


271

Prawdopodobnie szukasz UIView -(BOOL)isDescendantOfView:(UIView *)view;wykonanych w odwołaniu do klasy UIView .

Wartość zwracana TAK, jeśli odbiorca jest bezpośrednim lub odległym podziałem widoku lub jeśli widok jest samym odbiornikiem; inaczej NIE.

Otrzymasz kod taki jak:

Cel C

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

Szybki 3

@IBAction func showPopup(sender: AnyObject) {
    if !self.myView.isDescendant(of: self.view) {
        self.view.addSubview(self.myView)
    } else {
        self.myView.removeFromSuperview()
    }
}

2
Nie działa, po prostu dodaje widok na to.
Zmodyfikuję

@ zad0xsis - nie rozumiem prawdziwego przypadku. Jeśli dodałeś drugi widok za pomocą addSubview:metody (co prawdopodobnie dzieje się za pierwszym razem), następnym razem dotrzesz do innej części, ponieważ drugi widok jest teraz podziałem pierwszego. Czy to nie jest to, co próbowałeś zrobić? Może szukasz innego mekanizmu, jak modalne prezentowanie kontrolera widoku?

no cóż, popoverViewjest to widok podrzędny rootView (rootViewController). Chcę sprawdzić, czy jest na ekranie (jeśli ma rootView jako superview) i jeśli tak, usuń go lub dodaj, jeśli nie jest
pmerino

czy [self popoverView]za każdym razem zwraca nowo utworzony popover? nie może dodać widoku „ponad nim”, jeśli jest to ten sam widok, dodając widok, który już nie jest dostępny. jeśli za popoverViewkażdym razem metoda tworzy nową, to zawsze nie będzie w hierarchii
widoków

1
Jedna ważna kwestia, która mnie tu zaskoczyła: podczas usuwania, a następnie dodawania podglądów podrzędnych, które trzymasz za pomocą właściwości IBOutlet (lub ivarów), musisz upewnić się, że właściwości (ivars) są mocne lub że (przed ARC) są zachowane . Domyślnie, jeśli przeciągniesz, przytrzymując klawisz Ctrl, z widoku do kontrolera, aby utworzyć gniazdo, utworzy on go jako słaby, ponieważ zakłada, że ​​widok utworzony w końcówce będzie go właścicielem, więc nie potrzebujesz silnego odniesienia. Ale jeśli następnie usuniesz go programowo, zwolni to kontrolę i ustawi twoje odniesienie na nil (w ARC).
Rabarbar

18

Spróbuj tego:

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

niesamowite! czasami potrzebuje myView.view.superview, ale dla mnie działało jak magia. Dzięki @MarkGranoff
Lior Frenkel

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

Nie działa, po prostu dodaje widok na to. Zmodyfikuję kod, aby pokazać prawdziwy przypadek - zad0xsis 1 min temu edit
pmerino

12
@pmerino Gratulacje za lenistwo, że również skopiowałeś "zad0xsis 1 min temu edit" :-)
Thomas Kekeisen

Myślę, że jest to droższe niż inne rozwiązania, szczerze mówiąc, ponieważ musi iterować przez wszystkie podglądy
SimplyKiwi

4

Odpowiednik Swift będzie wyglądał mniej więcej tak:

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

2

Sprawdź podgląd podwidoku ...

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

1

Twój stan powinien być podobny

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

}

To jest niewielka modyfikacja odpowiedzi Michaela Fredericka. Czy daje inne wyniki niż kod Vincenta, który używa isDescendantOfView:?
paulmelnikow

To absolutnie daje inny rezultat. Sprawdza tylko, czy jest to widok dziecka, a nie wnuka lub prawnuka itp.
Sami Samhuri

0

Tutaj zastosowaliśmy dwa różne widoki. Widok nadrzędny to widok, w którym szukamy widoku potomnego i sprawdzamy, czy został dodany do widoku rodzica, czy nie.

if parentView.subviews.contains(descendantView) {
   // descendant view added to the parent view.
}else{
  // descendant view not added to the parent view.
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.