Odpowiedzi:
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 na subviews
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:
NSArray *viewsToRemove = [self.view subviews];
for (UIView *v in viewsToRemove) {
[v removeFromSuperview];
}
self.view
tak jak ty.
for (UIView *v in [self.view subviews])
jest łatwiej
W Swift możesz zastosować takie funkcjonalne podejście :
view.subviews.forEach { $0.removeFromSuperview() }
Dla porównania, imperatywne podejście wyglądałoby tak:
for subview in view.subviews {
subview.removeFromSuperview()
}
Te fragmenty kodu działają jednak tylko w systemie iOS / tvOS , w systemie macOS sytuacja wygląda nieco inaczej.
(subviews as [UIView]).map { $0.removeFromSuperview() }
.map
. jest to czysty efekt uboczny i lepiej sobie z nim view.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:
[[yourView subviews] makeObjectsPerformSelector: @selector(removeFromSuperview)];
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:
for (int i=mySuperView.subviews.count-1; i>=0; i--)
[[mySuperView.subviews objectAtIndex:i] removeFromSuperview];
SWIFT 1.2
for var i=mySuperView.subviews.count-1; i>=0; i-- {
mySuperView.subviews[i].removeFromSuperview();
}
lub (mniej wydajny, ale bardziej czytelny)
for subview in mySuperView.subviews.reverse() {
subview.removeFromSuperview()
}
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
[[someUIView subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
NIE powinien być używany.
Cytat z dokumentacji Apple na temat makeObjectsPerformSelector :
Wysyła do każdego obiektu w tablicy komunikat zidentyfikowany przez dany selektor, zaczynając od pierwszego obiektu i kontynuując przez tablicę do ostatniego obiektu.
(co byłoby niewłaściwym kierunkiem do tego celu)
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
view.subviews.forEach { $0.removeFromSuperview() }
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.
for (UIView *view in [self.view subviews])
{
[view removeFromSuperview];
}
W celu usunięcia wszystkich widoków podrzędnych Składnia:
- (void)makeObjectsPerformSelector:(SEL)aSelector;
Stosowanie :
[self.View.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
Ta metoda jest obecna w pliku NSArray.h i wykorzystuje interfejs NSArray (NSExtendedArray)
Jeśli używasz Swift, jest to tak proste, jak:
subviews.map { $0.removeFromSuperview }
W filozofii jest podobny do makeObjectsPerformSelector
podejścia, jednak z nieco większym bezpieczeństwem typu.
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.
NSMutableArray * constraints_to_remove = [ @[] mutableCopy] ;
for( NSLayoutConstraint * constraint in tagview.constraints) {
if( [tagview.subviews containsObject:constraint.firstItem] ||
[tagview.subviews containsObject:constraint.secondItem] ) {
[constraints_to_remove addObject:constraint];
}
}
[tagview removeConstraints:constraints_to_remove];
[ [tagview subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
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.
W monotouch / xamarin.ios zadziałało to dla mnie:
SomeParentUiView.Subviews.All(x => x.RemoveFromSuperview);
Aby usunąć wszystkie podviewy z superviews:
NSArray *oSubView = [self subviews];
for(int iCount = 0; iCount < [oSubView count]; iCount++)
{
id object = [oSubView objectAtIndex:iCount];
[object removeFromSuperview];
iCount--;
}
iCount++
i iCount--
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.