Gdy moja aplikacja wróci do kontrolera widoku głównego, w viewDidAppear:
metodzie muszę usunąć wszystkie widoki podrzędne.
W jaki sposób mogę to zrobić?
Edit: Z podziękowaniami dla cocoafan : Ta sytuacja jest zagmatwane przez fakt, że NSView
i UIView
rzeczy rękojeść inaczej. W przypadku NSView
(tylko programowanie na komputery Mac) możesz po prostu użyć następujących opcji:
[someNSView setSubviews:[NSArray array]];
W przypadku UIView
(tylko programowanie na iOS) można bezpiecznie korzystać, makeObjectsPerformSelector:
ponieważ subviews
właściwość zwróci kopię tablicy podrzędnych widoków:
[[someUIView subviews]
makeObjectsPerformSelector:@selector(removeFromSuperview)];
Dziękujemy Tommy'emu za wskazanie, że makeObjectsPerformSelector:
wygląda na to, że modyfikuje subviews
tablicę podczas jej wyliczania (co robi dla NSView
, ale nie dla UIView
).
Zobacz to SO pytanie, aby uzyskać więcej informacji.
Uwaga: użycie jednej z tych dwóch metod usunie każdy widok, który zawiera widok główny, i zwolni je , jeśli nie zostaną zachowane w innym miejscu. Z dokumentacji Apple na removeFromSuperview :
Jeśli nadzór odbiornika nie jest zerowy, ta metoda zwalnia odbiorcę. Jeśli planujesz ponownie użyć widoku, pamiętaj o jego zachowaniu przed wywołaniem tej metody i pamiętaj, aby odpowiednio go zwolnić po zakończeniu pracy lub po dodaniu go do innej hierarchii widoków.
UIView
Zwraca kopiowania nasubviews
zmienny tablicy, więc ten kod po prostu działa. Zupełnie inna historia na pulpicie, gdzie ten sam kod zgłosi wyjątek. Zobacz stackoverflow.com/questions/4665179/…someUIView.Subviews.All( v => { v.RemoveFromSuperview(); return true; } );
. IMHO czystsze powiedzieć, co to znaczy:someUIView.Subviews.ToList().ForEach( v => v.RemoveFromSuperview() );
.Pobierz wszystkie widoki podrzędne z kontrolera głównego i wyślij każdemu removeFromSuperview:
źródło
self.view
tak jak ty.for (UIView *v in [self.view subviews])
jest łatwiejW Swift możesz zastosować takie funkcjonalne podejście :
Dla porównania, imperatywne podejście wyglądałoby tak:
Te fragmenty kodu działają jednak tylko w systemie iOS / tvOS , w systemie macOS sytuacja wygląda nieco inaczej.
źródło
(subviews as [UIView]).map { $0.removeFromSuperview() }
.map
. jest to czysty efekt uboczny i lepiej sobie z nimview.subviews.forEach() { $0.removeFromSuperview() }
Jeśli chcesz usunąć wszystkie widoki podrzędne na swoim UIView (tutaj
yourView
), to napisz ten kod na kliknięcie przycisku:źródło
Dotyczy to tylko OSX, ponieważ w iOS przechowywana jest kopia tablicy
Podczas usuwania wszystkich widoków podrzędnych dobrym pomysłem jest rozpoczęcie usuwania na końcu tablicy i kontynuowanie usuwania aż do początku. Można to osiągnąć za pomocą dwóch wierszy kodu:
SWIFT 1.2
lub (mniej wydajny, ale bardziej czytelny)
UWAGA
NIE powinieneś usuwać widoków podrzędnych w normalnej kolejności, ponieważ może to spowodować awarię, jeśli instancja UIView zostanie usunięta przed
removeFromSuperview
wysłaniem wiadomości do wszystkich obiektów tablicy. (Oczywiście usunięcie ostatniego elementu nie spowoduje awarii)Dlatego kod
NIE powinien być używany.
Cytat z dokumentacji Apple na temat makeObjectsPerformSelector :
(co byłoby niewłaściwym kierunkiem do tego celu)
źródło
removeFromSuperview
zakończeniu UIView zostanie usunięty z tablicy, a jeśli nie będzie innych żywych instancji silnie powiązanych z UIView, UIView również zostanie usunięty. Może to spowodować wyjątek spoza zakresu.[yourView subviews]
zwraca COPY tablicy, dlatego jest bezpieczny. (UWAGA, że w OSX to, co mówisz, jest poprawne.)Wypróbuj w ten sposób swift 2.0
źródło
forEach
rozwiązanie bazowe zostało dodane po twoim, przegapiłem to. Przeprosiny.Użyj następującego kodu, aby usunąć wszystkie widoki podrzędne.
źródło
Korzystanie z
UIView
rozszerzenia Swift :źródło
W celu C idź dalej i stwórz metodę kategorii poza klasą UIView.
źródło
źródło
W celu usunięcia wszystkich widoków podrzędnych Składnia:
Stosowanie :
Ta metoda jest obecna w pliku NSArray.h i wykorzystuje interfejs NSArray (NSExtendedArray)
źródło
Jeśli używasz Swift, jest to tak proste, jak:
W filozofii jest podobny do
makeObjectsPerformSelector
podejścia, jednak z nieco większym bezpieczeństwem typu.źródło
map
nie powinno powodować skutków ubocznych. Ponadto ten sam wynik można osiągnąć za pomocąforEach
.W przypadku ios6 korzystającego z autolayout musiałem dodać trochę kodu, aby usunąć ograniczenia.
Jestem pewien, że jest to lepszy sposób, ale zadziałało to dla mnie. W moim przypadku nie mogłem użyć bezpośredniego,
[tagview removeConstraints:tagview.constraints]
ponieważ w XCode były ustawione ograniczenia, które były usuwane.źródło
W monotouch / xamarin.ios zadziałało to dla mnie:
źródło
Aby usunąć wszystkie podviewy z superviews:
źródło
iCount++
iiCount--
pozostawiając ten sam indeks, więc będzie to nieskończona pętla jeśli[oSubView count]>0
. Jest to zdecydowanie błąd i NIE MOŻNA użyć kodu.