UIStackView:是否真的需要同时调用removeFromSuperView和removeArrangedSubview来删除子视图?


71

UIStackView类参考

在removeArrangedSubview中:

为防止在调用堆栈的removeArrangedSubview:方法后视图出现在屏幕上,请通过调用视图的removeFromSuperview方法从子视图数组中显式删除视图。

在布置子视图中:

每当调用已安排视图的removeFromSuperview方法时,堆栈视图就会将该视图从其organizedSubview数组中删除。

从这些看来,仅调用removeFromSuperview就足以删除一个子视图,而我一直在使用它而没有问题。当调用removeFromSuperview时,我还通过记录rangingSubviews数组的计数来确认此行为。

但是,这里有许多有关S / O的教程和评论,请两者都称呼。是否有一个原因?还是人们只是因为文档中的说明而这样做?


4
对于您来说,这不是一个正确的答案,而是一个轶事:我只是在打电话时removeArrangedSubview不知道自己也应该打电话removeFromSuperview,这确实清除了观点,arrangedSubviews但观点仍在subviews引起各种混乱的破坏。添加removeFromSuperview呼叫(一旦我看到这个问题!)就解决了。
aehlke '16

我也不知道答案。但是我遇到一个问题,在使用RemoveArrangedSubview之后,我的所有子视图都没有被删除。看到这篇文章后,我添加了removeFromSuperview调用,现在它可以按预期工作。
CleverPatrick

1
该文档似乎建议您只需致电removeFromSuperview。我只打电话removeFromSuperview没有任何问题。
亚当·约翰斯

通过仅调用removeArrangedSubview,似乎IOS12存在问题。它没有正确删除视图。仅调用removeFromSuperview即可。
Seeler99

Answers:


78

不,只要打电话 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)

1
实际上,这是一个错误的解释。只是使用removeFromSuperView()似乎可以工作,但是如果要添加和删除很多视图,可能会导致奇怪的崩溃。如果您阅读了文档的讨论部分,则很明显,您必须同时调用两者。
drekka

4
您可以引用@drekka或提供链接吗?该文档似乎很清楚不需要两个调用。
Graham Perks

我可以确认这一点,removeFromSuperview()仅在致电时我的应用程序就有崩溃报告。我将在不久后发布一个更新,其中还会添加removeArrangedSubview()并报告此修复程序!
simonthumper

1
@simonthumper修复了吗?
吉尔·伯曼

我正在使用removeArrangedSubview从stackView中删除2个按钮,删除后我仍然有它们(仅修改了框架)。使用func后,removeArrangedView(_ view:UIView){removeArrangedSubview(view)view.removeFromSuperview()}一切都很好:)
Deryck Lucian

31

在iOS 12.0中,您需要使用

stackView.arrangedSubviews[index].removeFromSuperview()

如果使用removeArrangedSubview,则存在一个错误,该错误已删除指定索引处的视图,但要清除的视图显示在CGPoint(x: 0, y: 0)

希望这可以帮助某人。


遇到这个问题2.这个大日志在哪里?
H2wk '18年

10

在这种情况下,使用Web视图可以很好地利用Swift进行黑客攻击和解释。

原因是您可以从堆栈视图的已排列子视图列表中删除某些内容,然后在以后重新添加它,而不必每次都重新创建它-它是隐藏的,不会被破坏。我们不希望发生内存泄漏,因此我们希望完全删除已删除的Web视图。如果发现内存使用量激增,则可能忘记了这一步!

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


2
hackingwithswift已更新为仅推荐removeFromSuperview
Joachim Kurz

8

没错,只需调用即可removeFromSuperview完全删除视图。

我怀疑人们把两者都放的原因是因为他们遍历整个removeArrangedSubview文档,似乎都需要两者。(确实,如果您打电话removeArrangedSubview并希望视图真正消失,它们确实是。)

arrangedSubviews太多人看不到额外的文档,因此他们没有意识到removeArrangedSubview在这种情况下是可选的。


就像我在上面的评论中说的那样,它似乎可以工作,但可能会导致崩溃。因此,removeFromSuperview()不建议仅使用。
drekka

7

要从stackview中删除一个assembledSubview是

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

removeFromSuperview()根据Apple的说明文件就足够了,因为您也可以轻松地进行自我测试。removeArrangedSubview()根本没有必要。
约阿希姆·库兹

3

为了删除我使用此扩展名。真的不知道是否有必要删除约束。但也许会有所帮助。

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
只要删除的视图被立即销毁就可以了。但如果重复使用存在的潜在问题-所有的内部约束已被删除,因此可能不会正确布局
富托利

2

不,要删除特定视图。

func removeArrangedSubview(_ view:UIView)

删除所有子视图

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


0

我建议获取安排好的子视图,然后像下面的代码一样将其删除。

for view in self.stackView.arrangedSubviews{
      self.stackView.removeArrangedSubview(view)
      view.removeFromSuperview()
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.