Skip to content

Instantly share code, notes, and snippets.

@Deub27
Created November 25, 2017 14:00
Show Gist options
  • Select an option

  • Save Deub27/5eadbf1b77ce28abd9b630eadb95c1e2 to your computer and use it in GitHub Desktop.

Select an option

Save Deub27/5eadbf1b77ce28abd9b630eadb95c1e2 to your computer and use it in GitHub Desktop.
Remove all arranged subviews from UIStackView at once
import UIKit
extension UIStackView {
func removeAllArrangedSubviews() {
let removedSubviews = arrangedSubviews.reduce([]) { (allSubviews, subview) -> [UIView] in
self.removeArrangedSubview(subview)
return allSubviews + [subview]
}
// Deactivate all constraints
NSLayoutConstraint.deactivate(removedSubviews.flatMap({ $0.constraints }))
// Remove the views from self
removedSubviews.forEach({ $0.removeFromSuperview() })
}
}
@pronebird

Copy link
Copy Markdown

Is there any point to deactivate constraints given that removeFromSuperview removes them anyway?

@NikKovIos

NikKovIos commented May 31, 2018

Copy link
Copy Markdown

Removing constraints rely to this issue https://stackoverflow.com/questions/41054308/swift-crash-on-removefromsuperview but i think it's not necessary.

@shivanand217

Copy link
Copy Markdown

can you please modify to remove the first inserted or last inserted arrangedView. It will be a great help.

@shivanand217

shivanand217 commented Sep 24, 2018

Copy link
Copy Markdown

Gotcha brute force :P

extension UIStackView {
    
    func removeFirstArrangedView() {
        
        for item in arrangedSubviews {
            removeArrangedSubview(item)
            item.removeFromSuperview()
            break
        }
    }
   
   var i=1
   func removeLastArrangedView() {
        
           
    for item in arrangedSubviews {
        if i == arrangedSubviews.count {
            removeArrangedSubview(item)
            item.removeFromSuperview()
        }
        i+=1
    }
   } 
}

@magpali

magpali commented Jan 24, 2019

Copy link
Copy Markdown

Couldn't you deactivate the constraints and removeFromSuperview inside the nextPartialResult closure?
That way you wouldn't need to run through the whole array 3 times.

Something like

@discardableResult
func removeAllArrangedSubviews() -> [UIView] {
        let removedSubviews = arrangedSubviews.reduce([]) { (removedSubviews, subview) -> [UIView] in
            self.removeArrangedSubview(subview)
            NSLayoutConstraint.deactivate(subview.constraints)
            subview.removeFromSuperview()
            return removedSubviews + [subview]
        }
        return removedSubviews
    }

@hemangshah

Copy link
Copy Markdown

If someone will confuse on how to use magpali code then here's the same:

extension UIStackView {
    @discardableResult func removeAllArrangedSubviews() -> [UIView] {
        let removedSubviews = arrangedSubviews.reduce([]) { (removedSubviews, subview) -> [UIView] in
            self.removeArrangedSubview(subview)
            NSLayoutConstraint.deactivate(subview.constraints)
            subview.removeFromSuperview()
            return removedSubviews + [subview]
        }
        return removedSubviews
    }
}

@andrrrr

andrrrr commented Dec 10, 2019

Copy link
Copy Markdown

Or you can do it like this:

stack.arrangedSubviews
            .filter({ $0 is SomeView })
            .forEach({ $0.removeFromSuperview() })

@yasirmturk

Copy link
Copy Markdown

@finebel

finebel commented Aug 20, 2020

Copy link
Copy Markdown

Please corret me if I'm wrong but from my understanding you could simply do the following to remove all arrangedSubviews:

extension UIStackView {
    func removeAllArrangedSubviews() {
        arrangedSubviews.forEach {
            self.removeArrangedSubview($0)
            NSLayoutConstraint.deactivate($0.constraints)
            $0.removeFromSuperview()
        }
    }
}

@uvios

uvios commented Sep 17, 2020

Copy link
Copy Markdown

Worked like a charm 👍

@igorleonovich

igorleonovich commented Feb 27, 2024

Copy link
Copy Markdown

Just the SnapKit version:

import UIKit
import SnapKit

extension UIStackView {
    
    func removeArrangedSubviews() {
        guard !arrangedSubviews.isEmpty else { return }
        let subviewsToRemove = arrangedSubviews.reduce([]) { allSubviews, subview -> [UIView] in
            self.removeArrangedSubview(subview)
            return allSubviews + [subview]
        }
        subviewsToRemove.forEach { subview in
            subview.snp.removeConstraints()
            subview.removeFromSuperview()
        }
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment