当我的应用回到其根视图控制器时,在该viewDidAppear:
方法中,我需要删除所有子视图。
我怎样才能做到这一点?
当我的应用回到其根视图控制器时,在该viewDidAppear:
方法中,我需要删除所有子视图。
我怎样才能做到这一点?
Answers:
编辑:感谢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的文档中:
如果接收方的超级视图不为零,则此方法释放接收方。如果计划重用该视图,请确保在调用此方法之前保留该视图,并确保在完成该视图或将其添加到另一个视图层次结构后将其适当地释放。
UIView
返回一个副本中的subviews
可变数组,所以这段代码只是工作。桌面上完全不同的故事,相同的代码将引发异常。见stackoverflow.com/questions/4665179/...
someUIView.Subviews.All( v => { v.RemoveFromSuperview(); return true; } );
。恕我直言,清洁工说你的意思: someUIView.Subviews.ToList().ForEach( v => v.RemoveFromSuperview() );
。
从根控制器获取所有子视图,并将每个子视图发送给removeFromSuperview:
NSArray *viewsToRemove = [self.view subviews];
for (UIView *v in viewsToRemove) {
[v removeFromSuperview];
}
self.view
像你一样习惯。
for (UIView *v in [self.view subviews])
它更容易
在Swift中,您可以使用如下功能方法:
view.subviews.forEach { $0.removeFromSuperview() }
作为比较,命令式方法如下所示:
for subview in view.subviews {
subview.removeFromSuperview()
}
这些代码段仅在iOS / tvOS中有效,但是在macOS上则有所不同。
(subviews as [UIView]).map { $0.removeFromSuperview() }
.map
。这是纯粹的副作用,可以这样处理:view.subviews.forEach() { $0.removeFromSuperview() }
这仅适用于OSX,因为在iOS中会保留阵列的副本
删除所有子视图时,最好在数组末尾开始删除,并一直删除直到到达开头为止。这可以通过以下两行代码来完成:
for (int i=mySuperView.subviews.count-1; i>=0; i--)
[[mySuperView.subviews objectAtIndex:i] removeFromSuperview];
SWIFT 1.2
for var i=mySuperView.subviews.count-1; i>=0; i-- {
mySuperView.subviews[i].removeFromSuperview();
}
或(效率较低,但可读性更高)
for subview in mySuperView.subviews.reverse() {
subview.removeFromSuperview()
}
注意
您应该不删除子视图是正常的顺序,因为这可能会导致崩溃,如果前一个UIView实例被删除removeFromSuperview
的消息已发送到阵列的所有对象。(显然,删除最后一个元素不会导致崩溃)
因此,代码
[[someUIView subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
应该不被使用。
Apple文档中关于makeObjectsPerformSelector的引用:
将给定选择器标识的消息发送到数组中的每个对象,从第一个对象开始,一直到数组的最后一个对象。
(这将是错误的方向)
removeFromSuperview
完成时,UIView的会从数组中删除,如果有一个强有力的关系UIView的没有其他生活的情况下,UIView的也将被删除。这可能会导致超出范围的异常。
[yourView subviews]
返回数组的COPY,因此是安全的。(请注意,在OSX上您所说的是正确的。)
尝试这种方式swift 2.0
view.subviews.forEach { $0.removeFromSuperview() }
forEach
基础解决方案是在您之后添加的,我错过了。道歉。
view.subviews.forEach { $0.removeFromSuperview() }
为了删除所有子视图语法:
- (void)makeObjectsPerformSelector:(SEL)aSelector;
用法:
[self.View.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
此方法存在于NSArray.h文件中,并使用NSArray(NSExtendedArray)接口
如果您使用的是Swift,则非常简单:
subviews.map { $0.removeFromSuperview }
它在原理上与该makeObjectsPerformSelector
方法相似,但是类型安全性更高。
map
不应导致副作用。另外,可以通过获得相同的结果forEach
。
对于使用自动布局的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中设置的约束已被清除。
为了从超级视图中删除所有子视图:
NSArray *oSubView = [self subviews];
for(int iCount = 0; iCount < [oSubView count]; iCount++)
{
id object = [oSubView objectAtIndex:iCount];
[object removeFromSuperview];
iCount--;
}
iCount++
和iCount--
,使指数相同,所以这将是,如果一个无限循环[oSubView count]>0
。这绝对是错误的,不是可用的代码。