如何删除所有子视图?

当我的应用程序回到它的根视图控制器时,在viewDidAppear:方法中,我需要删除所有子视图。

我该怎么做呢?

179771 次浏览

由于cocoafan:由于NSViewUIView处理事情的方式不同,这种情况被混淆了。对于NSView(仅用于桌面Mac开发),您可以简单地使用以下命令:

[someNSView setSubviews:[NSArray array]];

对于UIView(仅限iOS开发),你可以安全地使用makeObjectsPerformSelector:,因为subviews属性将返回子视图数组的复制:

[[someUIView subviews]
makeObjectsPerformSelector:@selector(removeFromSuperview)];

感谢汤米指出,makeObjectsPerformSelector:似乎在被枚举时修改了subviews数组(它对NSView这样做,但对UIView没有)。

更多细节请参见这个SO问题

使用这两种方法中的任何一种都将删除你的主视图包含然后释放它们的每个视图,如果它们没有保留在其他地方。来自Apple在removeFromSuperview上的文档:

如果接收器的父视图不是nil,这个方法会释放接收器。如果您计划重用视图,请确保在调用此方法之前保留它,并确保在您完成它或将它添加到另一个视图层次结构之后适当地释放它。

从你的根控制器获取所有的子视图,并给每个子视图发送一个removeFromSuperview:

NSArray *viewsToRemove = [self.view subviews];
for (UIView *v in viewsToRemove) {
[v removeFromSuperview];
}

如果你想移除UIView上的所有子视图(这里是yourView),那么在你的按钮点击处编写以下代码:

[[yourView subviews] makeObjectsPerformSelector: @selector(removeFromSuperview)];

对于使用自动布局的ios6,我不得不添加一些代码来消除限制。

NSMutableArray * constraints_to_remove = [ @[] mutableCopy] ;
for( NSLayoutConstraint * constraint in tagview.constraints) {
if( [tagview.subviews containsObject:constraint.firstItem] ||
[tagview.subviews containsObject:constraint.secondItem] ) {
[constraints_to_remove addObject:constraint];
}
}
[tagview removeConstraints:constraints_to_remove];


[ [tagview subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];

我相信还有更简洁的方法,但这对我来说很管用。在我的情况下,我不能使用直接[tagview removeConstraints:tagview.constraints],因为在XCode中设置的约束正在被清除。

为了删除所有子视图

- (void)makeObjectsPerformSelector:(SEL)aSelector;

用法:

[self.View.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];

该方法存在于NSArray.h文件中,并使用NSArray(NSExtendedArray)接口

为了从父视图中移除所有子视图:

NSArray *oSubView = [self subviews];
for(int iCount = 0; iCount < [oSubView count]; iCount++)
{
id object = [oSubView objectAtIndex:iCount];
[object removeFromSuperview];
iCount--;
}

这只适用于OSX,因为在iOS中保留了数组的副本

在删除所有子视图时,最好从数组的末尾开始删除,并一直删除到数组的开头。这可以通过以下两行代码来实现:

for (int i=mySuperView.subviews.count-1; i>=0; i--)
[[mySuperView.subviews objectAtIndex:i] removeFromSuperview];

斯威夫特1.2

for var i=mySuperView.subviews.count-1; i>=0; i-- {
mySuperView.subviews[i].removeFromSuperview();
}

或者(效率较低,但可读性更好)

for subview in mySuperView.subviews.reverse() {
subview.removeFromSuperview()
}

请注意

你应该以正常的顺序删除子视图,因为如果在removeFromSuperview消息被发送到数组的所有对象之前删除UIView实例,可能会导致崩溃。(显然,删除最后一个元素不会导致崩溃)

因此,代码

[[someUIView subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];

应该使用

引用自关于makeObjectsPerformSelector的苹果文档:

向数组中的每个对象发送给定对象标识的消息 选择器,从第一个对象开始,一直到

.数组到最后一个对象

(这是错误的方向)

斯威夫特中,你可以像这样使用功能的方法:

view.subviews.forEach { $0.removeFromSuperview() }

作为比较,命令式的方法看起来像这样:

for subview in view.subviews {
subview.removeFromSuperview()
}

这些代码片段只能在iOS / tvOS中工作,但在macOS上情况略有不同。

如果你正在使用Swift,它就像:

subviews.map { $0.removeFromSuperview }

它在哲学上类似于makeObjectsPerformSelector方法,但是有更多的类型安全性。

使用Swift UIView扩展:

extension UIView {
func removeAllSubviews() {
for subview in subviews {
subview.removeFromSuperview()
}
}
}

试试swift 2.0

view.subviews.forEach { $0.removeFromSuperview() }

在monotouch / xamarin。这对我来说很管用:

SomeParentUiView.Subviews.All(x => x.RemoveFromSuperview);

在objective-C中,创建一个类别方法脱离UIView类。

- (void)removeAllSubviews
{
for (UIView *subview in self.subviews)
[subview removeFromSuperview];
}

使用以下代码删除所有子视图。

for (UIView *view in [self.view subviews])
{
[view removeFromSuperview];
}
view.subviews.forEach { $0.removeFromSuperview() }