Wie entferne ich alle Unteransichten einer Ansicht in Swift?

176

Ich suche nach einer einfachen Methode, um alle Unteransichten auf einmal aus einer Übersicht zu entfernen, anstatt sie einzeln zu entfernen.

//I'm trying something like this, but is not working
let theSubviews : Array = container_view.subviews
for (view : NSView) in theSubviews {
    view.removeFromSuperview(container_view)
}

Was fehlt mir?

AKTUALISIEREN

Meine App hat eine Haupt container_view. Ich muss verschiedene andere Ansichten als Unteransichten hinzufügen container_view, um eine Art Navigation bereitzustellen.

Wenn ich also auf die Schaltfläche klicke, um eine bestimmte Seite zu "öffnen", muss ich alle Unteransichten entfernen und die neue hinzufügen.

UPDATE 2 - Eine funktionierende Lösung (OS X)

Ich denke Apple hat es behoben.

Jetzt ist es einfacher als je zuvor. Rufen Sie einfach an:

for view in containerView.subviews{
    view.removeFromSuperview()
}
Alberto Bellini
quelle
2
Ich möchte darauf hinweisen, dass @ sulthans Antwort, während sie mit den Lumpen begraben ist, die überlegene Antwort ist: stackoverflow.com/questions/24312760/…
Christopher Swasey
@ChristopherSwasey Swift 4 gibt einen Fehler aus: Kann der Eigenschaft nicht zugewiesen werden: 'subviews' ist eine Nur-Get-Eigenschaft. :(
William T. Mallard
2
@ WilliamT.Mallard Wie oft muss wiederholt werden, dass es sich bei dieser Methode und Frage um MacOS und nicht um iOS handelt?
Fogmeister

Antworten:

358

EDIT: (danke Jeremiah / Rollo)

Bei weitem der beste Weg, dies in Swift für iOS zu tun, ist:

view.subviews.forEach({ $0.removeFromSuperview() }) // this gets things done
view.subviews.map({ $0.removeFromSuperview() }) // this returns modified array

^^ Diese Funktionen machen Spaß!

let funTimes = ["Awesome","Crazy","WTF"]
extension String { 
    func readIt() {
        print(self)
    }
}

funTimes.forEach({ $0.readIt() })

//// END EDIT

Mach das einfach:

for view in self.view.subviews {
    view.removeFromSuperview()
}

Oder wenn Sie nach einer bestimmten Klasse suchen

for view:CustomViewClass! in self.view.subviews {
        if view.isKindOfClass(CustomViewClass) {
            view.doClassThing()
        }
    }
Bseaborn
quelle
In Xcode 7.0 Beta 6 wird eine Warnung generiert: "Ergebnis des Aufrufs von 'map' wird nicht verwendet". Ich hoffe, dass dies in der endgültigen Version behoben wird.
Ferschae Naej
Das habe ich auch bemerkt! Ich werde den Beitrag aktualisieren, sobald Xcode aus der Beta kommt und das Problem weiterhin besteht.
Bseaborn
8
Die Warnung result of call to 'map' is unused ist kein Fehler. Array.mapIn den meisten Sprachen wird das geänderte Array zurückgegeben. Die äquivalente Methode, die kein Array zurückgibt, wäre view.subviews.forEach.
Rollo
for view:CustomViewClass! in self.view.subviews where view.isKindOfClass(CustomViewClass) { view.doClassThing() }
iTSangar
Ich würde argumentieren, dass dies "bei weitem der beste Weg ist, dies in Swift zu tun", siehe stackoverflow.com/a/24314054/1974224
Cristik
41

Für iOS / Swift, um alle von mir verwendeten Unteransichten zu entfernen:

for v in view.subviews{
   v.removeFromSuperview()
}

Um alle Unteransichten einer bestimmten Klasse (wie UILabel) zu entfernen, verwende ich:

for v in view.subviews{
   if v is UILabel{
      v.removeFromSuperview()
   }
}
Tonethar
quelle
31

Der Code kann wie folgt einfacher geschrieben werden.

view.subviews.forEach { $0.removeFromSuperview() }
Mischimay
quelle
18

Dies sollte die einfachste Lösung sein.

let container_view: NSView = ...
container_view.subviews = []

( Weitere Methoden finden Sie unter Entfernen aller Unteransichten .)


Beachten Sie, dass dies eine MacOS- Frage ist und diese Antwort nur für MacOS funktioniert . Es funktioniert nicht unter iOS.

Sulthan
quelle
Dies ist definitiv der einfachste Weg ... removeFromSuperview wird automatisch für jede Ansicht aufgerufen, die sich nicht mehr im Unteransichts-Array befindet.
Christopher Swasey
2
@datayeah Das sind sie nicht, aber es gibt einen großen Unterschied zwischen NSView(OS X) und UIView(iOS).
Sulthan
@ Sulthan du hast recht. Ich bin hierher gekommen, um die schnelle Antwort für UIView zu erhalten, und habe nicht Ihr gesamtes Code-Snippet gelesen;)
datayeah
1
Swift 4 gibt einen Fehler aus: Kann der Eigenschaft nicht zugewiesen werden: 'Unteransichten' ist eine Nur-Get-Eigenschaft. :(
William T. Mallard
1
@AmrAngry Ich wiederhole noch einmal, dies war immer eine Mac OS-Frage NSView, nicht für iOS und UIView. Nur die Leute möchten die Frage und die Tags nicht lesen, daher wurden sie mit iOS-Antworten gefüllt.
Sulthan
10

Ich weiß nicht, ob Sie es geschafft haben, dieses Problem zu beheben, aber ich habe kürzlich ein ähnliches Problem festgestellt, bei dem die For-Schleife jedes Mal eine Ansicht verlassen hat. Ich fand dies, weil die self.subviews (vielleicht) mutiert waren, als removeFromSuperview () aufgerufen wurde.

Um dies zu beheben, habe ich:

let subViews: Array = self.subviews.copy()
for (var subview: NSView!) in subViews
{
    subview.removeFromSuperview()
}

Mit .copy () konnte ich jede Unteransicht entfernen, während das Array self.subviews mutiert wurde. Dies liegt daran, dass das kopierte Array (SubViews) alle Verweise auf die Objekte enthält und nicht mutiert ist.

EDIT: In Ihrem Fall denke ich, dass Sie verwenden würden:

let theSubviews: Array = container_view.subviews.copy()
for (var view: NSView!) in theSubviews
{
    view.removeFromSuperview()
}
Adam Richards
quelle
Funktioniert gut! Vielen Dank
Alberto Bellini
Hallo, versuchen Sie Folgendes, obwohl es wahrscheinlich einen viel eleganteren Weg gibt, dies zu tun: let subViewsArray: Array = (parentView.subviews as NSArray).copy() as Array<NSView>
Adam Richards
9

Versuche dies:

for view in container_view.subviews {
    view.removeFromSuperview()
}
MattL
quelle
9

Erweiterung zum Entfernen aller Unteransichten wird schnell entfernt.

import Foundation
import UIKit

extension UIView {
    /// Remove allSubView in view
    func removeAllSubViews() {
        self.subviews.forEach({ $0.removeFromSuperview() })
    }

}
YannSteph
quelle
1
Warum Karte? foreach vielleicht? subviews.forEach {$ 0.removeFromSuperview ()}
Zaporozhchenko Oleksandr
1
Ja, Sie haben Recht @Aleksandr Ich denke, als ich dies schrieb, hatte ich meinen Kaffee nicht genommen
YannSteph
6

Versuche dies:

var subViews = parentView.subviews as Array<UIView>

      for someView in subViews
      {
          someView.removeFromSuperview()
      }

UPDATE : Wenn Sie sich abenteuerlustig fühlen, können Sie die UIView wie folgt erweitern:

extension UIView
{
    func removeAllSubViews()
    {
       for subView :AnyObject in self.subviews
       {
            subView.removeFromSuperview()
       }
    }

}

Und nenne es so:

parentView.removeAllSubViews()
Azamsharp
quelle
2 kleine Dinge: Ich arbeite an osx, daher wäre es <NSView>, oder? Dann erhalte ich "schwerwiegender Fehler: Array-Index außerhalb des Bereichs": /
Alberto Bellini
Ja, ich denke unter OSX ist es NSView. Woher kommt der schwerwiegende Fehler?
Azamsharp
Sind Sie sicher, dass Ihre übergeordnete Ansicht untergeordnete Elemente enthält?
Azamsharp
Ja! Wenn ich einen Druck mache (parentView.subviews), bekomme ich 1
Alberto Bellini
Das ist komisch! Normalerweise bedeutet außerhalb des Bereichs, dass Sie auf einen Index zugreifen, der nicht existiert, und normalerweise glaube ich, dass dies durch die Verwendung einer for-Schleife mit Indizes wie i ++ verursacht wird.
Azamsharp
5

In xcodebeta6 hat das geklappt.

    var subViews = self.parentView.subviews
    for subview in subViews as [UIView]   {
        subview.removeFromSuperview()
    }
Hassbyte
quelle
Das ist iOS. Ich brauche eine Lösung für OS X
Alberto Bellini
Tolle Lösung für IOS +1
unbesiegbar
3

Ich habe diese Erweiterung geschrieben:

extension UIView {
    func lf_removeAllSubviews() {
        for view in self.subviews {
            view.removeFromSuperview()
        }
    }
}

Damit Sie self.view.lf_removeAllSubviews in einem UIViewController verwenden können. Ich werde dies später in die schnelle Version meines https://github.com/superarts/LFrameworks aufnehmen , wenn ich mehr Erfahrung mit Swift habe (1 Tag Erfahrung bisher, und ja, für API habe ich den Unterstrich aufgegeben).

superarts.org
quelle
3

Swift 3

Wenn Sie Ihrer Ansicht ein Tag hinzufügen, können Sie eine bestimmte Ansicht entfernen.

for v in (view?.subviews)!
{
    if v.tag == 321
    {
         v.removeFromSuperview()
    }
 }
uplearnedu.com
quelle
warum nicht view.subviews.filter({$0.tag != 321}).forEach({$0.removeFromSuperview()})?
AlexanderZ
3

Swift 5

Ich erstelle 2 verschiedene Methoden, um die Unteransicht zu entfernen. Und es ist viel einfacher zu bedienen, wenn wir sie einsetzenextension

extension UIView {
    /// Remove all subview
    func removeAllSubviews() {
        subviews.forEach { $0.removeFromSuperview() }
    }

    /// Remove all subview with specific type
    func removeAllSubviews<T: UIView>(type: T.Type) {
        subviews
            .filter { $0.isMember(of: type) }
            .forEach { $0.removeFromSuperview() }
    }
}
nahung89
quelle
2

Ihre Syntax ist leicht falsch. Stellen Sie sicher, dass Sie explizit besetzen.

 let theSubviews : Array<NSView> = container_view.subviews as Array<NSView>
 for view in theSubviews {
     view.removeFromSuperview()
 }
Jack
quelle
@ David Ja, ich habe versucht, es so nah wie möglich am ursprünglichen Code von FoxNos zu halten.
Jack
2

du musst das versuchen

func clearAllScrollSubView ()
{
    let theSubviews = itemsScrollView.subviews

    for (var view) in theSubviews
    {

        if view is UIView
        {
            view.removeFromSuperview()
        }

    }
}
Ahmed Zaytoun
quelle
Das ist UI nicht NS. Hier sprechen wir über OS X. Wenn das auch damit funktioniert, indem Sie die Benutzeroberfläche durch NS ersetzen, meine schlechte, Sie hatten Recht :)
Alberto Bellini
1

Zum Entfernen nur von Unteransichten einer bestimmten Klasse - dies war der einzige Swift-Code, der in Xcode6.1.1 für mich funktioniert hat. Angenommen, die einzigen Unteransichten, die Sie entfernen möchten, sind vom Typ UIButton ...

for subView in nameofmysuperview.subviews {
    if subView.isKindOfClass(UIButton) {
        subView.removeFromSuperview()
    }
}
Gammachill
quelle
1

Einzeiler:

while(view.subviews.count > 0) {(view.subviews[0] as NSView).removeFromSuperview()}

Ich denke, dieser Ansatz ist besser lesbar als die "Einzeiler" mit map oder forEach . Kurzes Foreach und Map können schwierig zu verstehen sein, da die Logik abstrakter ist.

Eonist
quelle
1

Für Swift 3

Ich habe Folgendes getan, weil durch einfaches Entfernen aus der Übersicht die Schaltflächen nicht aus dem Array gelöscht wurden.

    for k in 0..<buttons.count {

      buttons[k].removeFromSuperview()

    }


    buttons.removeAll()
Hoffnung
quelle
1

Probieren Sie es aus, ich habe dies getestet:

  let theSubviews = container_view.subviews
  for subview in theSubviews {
      subview.removeFromSuperview()
  }
Ezimet
quelle
1

Zum Swift 4.+

extension UIView {
     public func removeAllSubViews() {
          self.subviews.forEach({ $0.removeFromSuperview() })

}

Ich hoffe, dass dies für Sie voll genutzt wird.

Masoud Heydari
quelle
-2

Hast du so etwas versucht?

for o : AnyObject in self.subviews {
     if let v = o as? NSView {
         v.removeFromSuperview()
     }
}
Christian Dietrich
quelle