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

}
pmerino
źródło

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()
    }
}
dłoń
źródło
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];
}
Mark Granoff
źródło
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]) {
        ...
    }
Michael Frederick
źródło
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()
}
JaySH
źródło
2

Sprawdź podgląd podwidoku ...

-(IBAction)showPopup:(id)sender {
    if([[self myView] superview] == self.view) { 
        [[self myView] removeFromSuperview];           
    } else {
        [self.view addSubview:[self myView]];         
    }
}
Jason Harwig
źródło
1

Twój stan powinien być podobny

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

}
Saran
źródło
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.
}
shubham
źródło