当我的应用程序返回其根视图控制器时,viewDidAppear:
我需要在该方法中删除所有子视图。
我怎样才能做到这一点?
编辑:感谢cocoafan:这种情况因不同的处理方式NSView
而变得混乱UIView
。对于NSView
(仅限桌面 Mac 开发),您可以简单地使用以下内容:
[someNSView setSubviews:[NSArray array]];
对于UIView
(仅限 iOS 开发),您可以安全地使用makeObjectsPerformSelector:
,因为该subviews
属性将返回子视图数组的副本:
[[someUIView subviews]
makeObjectsPerformSelector:@selector(removeFromSuperview)];
感谢Tommy指出在枚举数组时makeObjectsPerformSelector:
似乎会修改subviews
数组(它对 进行NSView
,但对 没有UIView
)。
有关更多详细信息,请参阅此 SO 问题。
注意:使用这两种方法中的任何一种都会删除主视图包含的每个视图并释放它们,如果它们没有保留在其他地方。来自 Apple 关于removeFromSuperview的文档:
如果接收者的 superview 不为零,则此方法释放接收者。如果您打算重用视图,请确保在调用此方法之前保留它,并确保在使用完它或将其添加到另一个视图层次结构之后适当地释放它。
从你的根控制器获取所有子视图并发送一个 removeFromSuperview:
NSArray *viewsToRemove = [self.view subviews];
for (UIView *v in viewsToRemove) {
[v removeFromSuperview];
}
在Swift中,你可以使用这样的函数式方法:
view.subviews.forEach { $0.removeFromSuperview() }
作为比较,命令式方法如下所示:
for subview in view.subviews {
subview.removeFromSuperview()
}
这些代码片段仅适用于iOS / tvOS,但在 macOS 上有些不同。
如果要删除 UIView 上的所有子视图(此处yourView
),请在单击按钮时编写此代码:
[[yourView subviews] makeObjectsPerformSelector: @selector(removeFromSuperview)];
这仅适用于 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)];
不应该使用。
引用Apple 文档中关于 makeObjectsPerformSelector的内容:
向数组中的每个对象发送由给定选择器标识的消息,从第一个对象开始,然后通过数组继续到最后一个对象。
(为此目的,这将是错误的方向)
试试这种方式 swift 2.0
view.subviews.forEach { $0.removeFromSuperview() }
使用以下代码删除所有子视图。
for (UIView *view in [self.view subviews])
{
[view removeFromSuperview];
}
view.subviews.forEach { $0.removeFromSuperview() }
使用 SwiftUIView
扩展:
extension UIView {
func removeAllSubviews() {
for subview in subviews {
subview.removeFromSuperview()
}
}
}
在 Objective-C 中,继续从 UIView 类创建一个类别方法。
- (void)removeAllSubviews
{
for (UIView *subview in self.subviews)
[subview removeFromSuperview];
}
为了删除所有子视图语法:
- (void)makeObjectsPerformSelector:(SEL)aSelector;
用法 :
[self.View.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
此方法存在于 NSArray.h 文件中并使用 NSArray(NSExtendedArray) 接口
如果你使用的是 Swift,它很简单:
subviews.map { $0.removeFromSuperview }
它在哲学上与该makeObjectsPerformSelector
方法相似,但具有更多的类型安全性。
对于使用自动布局的 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 中设置的约束已被清除。
在 monotouch / xamarin.ios 这对我有用:
SomeParentUiView.Subviews.All(x => x.RemoveFromSuperview);
为了从超级视图中删除所有子视图:
NSArray *oSubView = [self subviews];
for(int iCount = 0; iCount < [oSubView count]; iCount++)
{
id object = [oSubView objectAtIndex:iCount];
[object removeFromSuperview];
iCount--;
}