UIStackView: 是否真的有必要同时调用 RemoveFromSuperView 和 RemoveOrganedSubview 来删除子视图?

来自 类引用

视图:

为了防止视图在调用堆栈的 RemoveOrganedSubview: 方法之后出现在屏幕上,可以通过调用视图的 RemoveFromSuperview 方法显式地从 subviews 数组中删除视图。

视图:

无论何时调用已排列视图的 RemoveFromSuperview 方法,堆栈视图都会将该视图从其安排的 Subview 数组中删除

从这些例子中可以看出,仅仅调用 RemoveFromSuperview 就足以删除一个子视图,而且我一直在这样使用它,没有遇到任何问题。我还通过在调用 RemoveFromSuperview 时记录 orgedSubviews 数组的计数来确认这一行为。

然而,这里有很多关于 S/O 的教程和注释,说两者都可以调用。有什么原因吗?还是人们这么做只是因为文件上这么说的?

43224 次浏览

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

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)

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.

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.

To remove a arrangedSubview from a stackview is

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

No, To remove specific view.

func removeArrangedSubview(_ view: UIView)

To remove all subviews

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

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

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

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