100

From the UIStackView Class Reference

In removeArrangedSubview:

To prevent the view from appearing on screen after calling the stack’s removeArrangedSubview: method, explicitly remove the view from the subviews array by calling the view’s removeFromSuperview method.

In arrangedSubview:

Whenever an arranged view’s removeFromSuperview method is called, the stack view removes the view from its arrangedSubview array

From these, it seems that calling just removeFromSuperview is enough to remove a subview and I've been using it like that without problems. I also confirmed the behavior by logging the count of the arrangedSubviews array when removeFromSuperview is called.

A lot of tutorials and comments here on S/O however, say to call both. Is there a reason for this? Or do people just do it because the documentation says so?

5
  • 10
    Not a proper answer for you, but an anecdote: I was only calling removeArrangedSubview without knowing I was supposed to also call removeFromSuperview, and it was indeed clearing the view from arrangedSubviews but the view was still appearing in subviews causing all kinds of confusing breakage. Adding the removeFromSuperview call (once I saw this question!) resolved it. Commented Aug 1, 2016 at 4:11
  • I don't know the answer, either. But I was having an issue where all my subviews were not being removed after using RemoveArrangedSubview. After seeing this post, I added removeFromSuperview calls and now it works as expected. Commented Aug 8, 2016 at 15:09
  • 2
    The documentation seems to suggest that you only need to call removeFromSuperview. I'm only calling removeFromSuperview without any issues. Commented Jan 4, 2017 at 21:59
  • Seems there is a problem with IOS12 by just calling removeArrangedSubview. It's not removing the view properly. Calling just removeFromSuperview works. Commented Sep 21, 2018 at 18:16
  • Calling removeArrangedSubview is not sufficient to remove the target subview from view hierarchy, as iOS 15, this is still the case. Commented May 13, 2022 at 2:40

9 Answers 9

119

No, just call subview.removeFromSuperview()

/* Removes a subview from the list of arranged subviews without removing it as
 a subview of the receiver.
    To remove the view as a subview, send it -removeFromSuperview as usual;
 the relevant UIStackView will remove it from its arrangedSubviews list
 automatically.
 */
open func removeArrangedSubview(_ view: UIView)
Sign up to request clarification or add additional context in comments.

5 Comments

Actually this is an incorrect interpretation. Just using removeFromSuperView() appears to work, but can cause weird crashes if you are adding and removing a lot of views. If you read the discussion part of the docs it's pretty clear you have to call both.
@drekka can you cite your source, or provide a link? The doc seems clear about not needing both calls.
I can confirm this, I have crash reports from my app when calling removeFromSuperview() only. I will be releasing an update shortly which also adds removeArrangedSubview() and report back on whether this fixes it!
@simonthumper did it fix it?
I was removing 2 buttons from stackView with removeArrangedSubview and I still had them after remove (only the frame was modified). after using func removeArrangedView(_ view: UIView) { removeArrangedSubview(view) view.removeFromSuperview() } everything is good :)
41

In iOS 12.0, You need to use

stackView.arrangedSubviews[index].removeFromSuperview()

If you use removeArrangedSubview, there is a bug where the view at the specified index removed, but the view I want to clear appears at CGPoint(x: 0, y: 0).

Hope this help someone.

1 Comment

Having this issue 2. Where abouts is the big log for this?
15

Hacking With Swift provides a pretty good example and explanation, using Web views in this case.

The reason is that you can remove something from a stack view's arranged subview list then re-add it later, without having to recreate it each time – it was hidden, not destroyed. We don't want a memory leak, so we want to remove deleted web views entirely. If you find your memory usage ballooning, you probably forgot this step!

https://www.hackingwithswift.com/read/31/4/removing-views-from-a-uistackview-with-removearrangedsubview

1 Comment

hackingwithswift was updated to also only recommend removeFromSuperview
14

To remove a arrangedSubview from a stackview is

// To remove it from the view hierarchy
   subView.removeFromSuperview()

2 Comments

removeFromSuperview() is enough, according to Apple‘s documentation and as you can also easily test yourself. removeArrangedSubview() is simply not necessary.
Calling removeArrangedSubview() only, actually will leave the view alive in the view hierarchy. It is a bug cost hours to debug, only when by dumping and checking the view hierarchy, I found the removed subview, is still in the view hierarchy, which is weird.
9

No, To remove specific view.

func removeArrangedSubview(_ view: UIView)

To remove all subviews

stackView.arrangedSubviews.forEach { $0.removeFromSuperview() }

2 Comments

The 2 lines are using different subview removal methods, thus are not doing the same. In some iOS versions removeArrangedSubview is not correct. You need to consistently call removeFromSuperview, which is the single call that works consistently, according to Apple doc and what all the others write here.
yeah lol wtf, and in the first example he doesn't call removeFromSuperview at all, which makes this answer absolutely 100% incorrect.
8

You're right, just the call to removeFromSuperview is sufficient to have the view fully removed.

I suspect the reason for people putting both is because they run across the removeArrangedSubview documentation which seems to say both are needed. (And indeed, they are, if you call removeArrangedSubview and want the view really gone.)

The additional doc in arrangedSubviews is not seen by so many, so they don't realize removeArrangedSubview is, in this case, optional.

1 Comment

As I said in a comment above, it may appear to work, but can trigger crashes. So just using removeFromSuperview() is not recommended.
4

For removing i use this extension. Don't really know is it necessary to remove constraints. But maybe it would help.

extension UIStackView {
    func removeAllArrangedSubviews() {
        let removedSubviews = arrangedSubviews.reduce([]) { (allSubviews, subview) -> [UIView] in
            self.removeArrangedSubview(subview)
            return allSubviews + [subview]
        }

        for v in removedSubviews {
            if v.superview != nil {
                NSLayoutConstraint.deactivate(v.constraints)
                v.removeFromSuperview()
            }
        }
    }
}

1 Comment

This is fine as long as the view removed is destroyed immediately. But there is a potential bug if it is reused - all the internal constraint have been removed so it will likely not layout correctly
2

I will suggest get arranged subviews then remove it like below code .

for view in self.stackView.arrangedSubviews{
      self.stackView.removeArrangedSubview(view)
      view.removeFromSuperview()
}

Comments

0

Simple answer: NO! (as previously stated by many others)

Longer answer:

// to remove "view" from the stack entirely 
// calls removeArrangedSubview()
view.removeFromSuperview() 
// to add "view" to the stack
// calls addSubview()
stackView.addArrangeSubview(view)

Please check out the explicit paragraph in Apple's documentation about this issue (Maintain consistency between the arranged views and subview): https://developer.apple.com/documentation/uikit/uistackview#1653129

Here is the important part:

The stack view ensures that its arrangedSubviews property is always a subset of its subviews property. Specifically, the stack view enforces the following rules: When the stack view adds a view to its arrangedSubviews array, it also adds that view as a subview, if it isn’t already. When a subview is removed from the stack view, the stack view also removes it from the arrangedSubviews array. Removing a view from the arrangedSubviews array doesn’t remove it as a subview. The stack view no longer manages the view’s size and position, but the view is still part of the view hierarchy, and is rendered on screen if it’s visible.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.