UIStackView:真的有必要同时调用removeFromSuperView和removeArratedSubvie



来自UIStackView类参考

在removeArratedSubview:中

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

在排列子视图中:

每当调用排列视图的removeFromSuperview方法时,堆栈视图都会从其排列子视图数组中删除该视图

从这些中,似乎只调用removeFromSuperview就足以删除子视图,我一直在这样使用它,没有遇到任何问题。我还通过记录调用removeFromSuperview时arrangedSubviews数组的计数来确认该行为。

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

不,只需调用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)

在iOS 12.0中,您需要使用

stackView.arrangedSubviews[index].removeFromSuperview()

如果使用removeArrangedSubview,则会出现一个错误,其中指定索引处的视图已删除,但我要清除的视图显示在CGPoint(x: 0, y: 0)处。

希望这能帮助到别人。

Hacking With Swift提供了一个很好的例子和解释,在本例中使用了Web视图。

原因是您可以从堆栈视图的排列子视图列表中删除某些内容,然后稍后重新添加,而不必每次都重新创建它——它是隐藏的,而不是销毁的。我们不希望内存泄漏,所以我们希望完全删除已删除的网络视图。如果你发现你的内存使用量激增,你可能忘记了这一步!

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

从stackview中删除arrangedSubview是

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

您是对的,只要调用removeFromSuperview就足以完全删除视图。

我怀疑人们把两者都放在一起的原因是他们遇到了removeArrangedSubview文档,该文档似乎说两者都是需要的。(事实上,如果你调用removeArrangedSubview并希望视图真的消失,它们就是。)

arrangedSubviews中的附加文档没有被很多人看到,所以他们没有意识到removeArrangedSubview在这种情况下是可选的。

否,删除特定视图。

func removeArrangedSubview(_ view: UIView)

删除所有子视图

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

要删除,请使用此扩展。不知道是否有必要取消限制。但也许这会有所帮助。

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

我建议获得排列好的子视图,然后像下面的代码一样删除它。

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

简单答案:NO!(正如之前许多其他人所说)

更长的答案:

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

请查看苹果公司文档中关于此问题的明确段落(Maintain consistency between the arranged views and subview):https://developer.apple.com/documentation/uikit/uistackview#1653129

这里是重要的部分:

堆栈视图确保其arrangedSubviews属性始终是其subviews属性的子集。特别是,堆栈视图强制执行以下规则:当堆栈视图将一个视图添加到其arrangedSubviews数组中时,如果该视图还没有添加,它也会将该视图添加为子视图。从堆栈视图中删除子视图时,堆栈视图也会将其从arrangedSubviews数组中删除。从arrangedSubviews数组中删除视图不会将其作为子视图删除。堆栈视图不再管理视图的大小和位置,但视图仍然是视图层次结构的一部分,如果可见,则会在屏幕上渲染。

相关内容

  • 没有找到相关文章

最新更新