How to remove all subviews of a view in Swift?

MacosViewSwift

Macos Problem Overview


I'm looking for a simple method to remove at once all subviews from a superview instead of removing them one by one.

//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)
}

What I am missing?

UPDATE

My app has a main container_view. I have to add different other views as subviews to container_view in order to provide a sort of navigation.

So, when clicking the button to "open" a particular page, I need to remove allsubviews and add the new one.

UPDATE 2 - A working solution (OS X)

I guess Apple fixed it.

Now it is more easy than ever, just call:

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

Macos Solutions


Solution 1 - Macos

EDIT: (thanks Jeremiah / Rollo)

By far the best way to do this in Swift for iOS is:

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

^^ These features are fun!

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

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

//// END EDIT

Just do this:

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

Or if you are looking for a specific class

for view:CustomViewClass! in self.view.subviews {
        if view.isKindOfClass(CustomViewClass) {
            view.doClassThing()
        }
    }

Solution 2 - Macos

For iOS/Swift, to get rid of all subviews I use:

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

to get rid of all subviews of a particular class (like UILabel) I use:

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

Solution 3 - Macos

The code can be written simpler as following.

view.subviews.forEach { $0.removeFromSuperview() }

Solution 4 - Macos

This should be the simplest solution.

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

(see https://stackoverflow.com/questions/2156015/remove-all-subviews for other methods)


Note this is a MacOS question and this answer works only for MacOS. It does not work on iOS.

Solution 5 - Macos

Swift 5

I create 2 different methods to remove subview. And it's much easier to use if we put them in extension

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() }
    }
}

Solution 6 - Macos

Try this:

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

Solution 7 - Macos

I don't know if you managed to resolve this but I have recently experienced a similar problem where the For loop left one view each time. I found this was because the self.subviews was mutated (maybe) when the removeFromSuperview() was called.

To fix this I did:

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

By doing .copy(), I could perform the removal of each subview while mutating the self.subviews array. This is because the copied array (subViews) contains all of the references to the objects and is not mutated.

EDIT: In your case I think you would use:

let theSubviews: Array = container_view.subviews.copy()
for (var view: NSView!) in theSubviews
{
    view.removeFromSuperview()
}

Solution 8 - Macos

Extension for remove all subviews, it is quickly removed.

import Foundation
import UIKit

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

}

Solution 9 - Macos

Try this:

var subViews = parentView.subviews as Array<UIView>
      
      for someView in subViews
      {
          someView.removeFromSuperview()
      }

UPDATE: If you are feeling adventurous then you can make an extension on the UIView as shown below:

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

}

And call it like this:

parentView.removeAllSubViews()

Solution 10 - Macos

In xcodebeta6 this worked out.

    var subViews = self.parentView.subviews
    for subview in subViews as [UIView]   {
        subview.removeFromSuperview()
    }

Solution 11 - Macos

Swift 3

If you add a tag to your view you can remove a specific view.

for v in (view?.subviews)!
{
    if v.tag == 321
    {
         v.removeFromSuperview()
    }
 }

Solution 12 - Macos

I wrote this extension:

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

So that you can use self.view.lf_removeAllSubviews in a UIViewController. I'll put this in the swift version of my https://github.com/superarts/LFramework later, when I have more experience in swift (1 day exp so far, and yes, for API I gave up underscore).

Solution 13 - Macos

Your syntax is slightly off. Make sure you cast explicitly.

 let theSubviews : Array<NSView> = container_view.subviews as Array<NSView>
 for view in theSubviews {
     view.removeFromSuperview()
 }

Solution 14 - Macos

you have to try this

func clearAllScrollSubView ()
{
    let theSubviews = itemsScrollView.subviews

    for (var view) in theSubviews
    {

        if view is UIView
        {
            view.removeFromSuperview()
        }

    }
}

Solution 15 - Macos

Try this out , I tested this :

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

Solution 16 - Macos

For removing just subviews of a specific class - this was the only Swift code that worked for me in Xcode6.1.1. Assuming the only subviews you want to remove are of type UIButton...

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

Solution 17 - Macos

For Swift 3

I did as following because just removing from superview did not erase the buttons from array.

    for k in 0..<buttons.count {
    
      buttons[k].removeFromSuperview()
        
    }
      

    buttons.removeAll()

Solution 18 - Macos

For Swift 4.+

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

}

i hope this is use full for you.

Solution 19 - Macos

One-liner:

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

Solution 20 - Macos

Here's a one-liner you've been looking for:

view.subviews.filter({$0.tag == 321}).forEach({$0.removeFromSuperview()})

Don't forget to Tag your view (someView.tag = 321) before you remove it with this code.

Solution 21 - Macos

Here's another approach that allows you call the operation on any collection of UIView instances (or UIView subclasses). This makes it easy to insert things like filter after .subviews so you can be more selective, or to call this on other collections of UIViews.

extension Array where Element: UIView {
  func removeEachFromSuperview() {
    forEach {
      $0.removeFromSuperview()
    }
  }
}

Example usage:

myView.subviews.removeEachFromSuperview()

// or, for example:

myView.subivews.filter { $0 is UIImageView }.removeEachFromSuperview()

Alternatively you can accomplish the same thing with a UIView extension (though this can't be called on some arbitrary array of UIView instances):

extension UIView {
    func removeSubviews(predicate: ((UIView) -> Bool)? = nil) 
        subviews.filter(
            predicate ?? { _ in true }
        ).forEach {
            $0.removeFromSuperview()
        }
    }
}

Example usage:

myView.removeSubviews()
myView.removeSubviews { $0 is UIImageView }

Solution 22 - Macos

did you try something like

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAlbertoView Question on Stackoverflow
Solution 1 - MacosBseabornView Answer on Stackoverflow
Solution 2 - MacostonetharView Answer on Stackoverflow
Solution 3 - MacosmishimayView Answer on Stackoverflow
Solution 4 - MacosSulthanView Answer on Stackoverflow
Solution 5 - Macosnahung89View Answer on Stackoverflow
Solution 6 - MacosMattLView Answer on Stackoverflow
Solution 7 - MacosAdam RichardsView Answer on Stackoverflow
Solution 8 - MacosYannStephView Answer on Stackoverflow
Solution 9 - MacosazamsharpView Answer on Stackoverflow
Solution 10 - MacosmylegfeelsfunnyView Answer on Stackoverflow
Solution 11 - Macosuplearned.comView Answer on Stackoverflow
Solution 12 - Macossuperarts.orgView Answer on Stackoverflow
Solution 13 - MacosJackView Answer on Stackoverflow
Solution 14 - MacosAhmed ZaytounView Answer on Stackoverflow
Solution 15 - MacosEzimetView Answer on Stackoverflow
Solution 16 - MacosgammachillView Answer on Stackoverflow
Solution 17 - MacosHopeView Answer on Stackoverflow
Solution 18 - MacosMasoud HeydariView Answer on Stackoverflow
Solution 19 - MacosSentry.coView Answer on Stackoverflow
Solution 20 - MacosCodetardView Answer on Stackoverflow
Solution 21 - MacosshimView Answer on Stackoverflow
Solution 22 - MacosChristian DietrichView Answer on Stackoverflow