【发布时间】:2011-01-10 11:48:04
【问题描述】:
当我的应用返回其根视图控制器时,我需要在 viewDidAppear: 方法中删除所有子视图。
我该怎么做?
【问题讨论】:
当我的应用返回其根视图控制器时,我需要在 viewDidAppear: 方法中删除所有子视图。
我该怎么做?
【问题讨论】:
这仅适用于 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()
}
注意
您应该不按正常顺序删除子视图,因为如果在removeFromSuperview 消息发送到数组的所有对象之前删除 UIView 实例,可能会导致崩溃。 (显然,删除最后一个元素不会导致崩溃)
因此,代码
[[someUIView subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
应该不使用。
引用Apple documentation about makeObjectsPerformSelector:
向数组中的每个对象发送由给定标识的消息 选择器,从第一个对象开始,一直到 数组到最后一个对象。
(这将是错误的方向)
【讨论】:
removeFromSuperview完成时,UIView将从数组中移除,如果没有其他与UIView有强关联的活实例,UIView也会被删除。这可能会导致超出范围的异常。
[yourView subviews] 返回数组的副本,因此是安全的。 (请注意,在 OSX 上,您所说的是正确的。)
view.subviews.forEach { $0.removeFromSuperview() }
【讨论】:
在 Swift 中,您可以像这样使用 函数式方法:
view.subviews.forEach { $0.removeFromSuperview() }
作为比较,命令式方法如下所示:
for subview in view.subviews {
subview.removeFromSuperview()
}
这些代码 sn-ps 仅适用于 iOS / tvOS,但在 macOS 上有些不同。
【讨论】:
(subviews as [UIView]).map { $0.removeFromSuperview() }
.map 的结果。这是一个纯粹的副作用,最好这样处理:view.subviews.forEach() { $0.removeFromSuperview() }
使用以下代码删除所有子视图。
for (UIView *view in [self.view subviews])
{
[view removeFromSuperview];
}
【讨论】:
在 Objective-C 中,继续从 UIView 类创建一个类别方法。
- (void)removeAllSubviews
{
for (UIView *subview in self.subviews)
[subview removeFromSuperview];
}
【讨论】:
在 monotouch / xamarin.ios 这对我有用:
SomeParentUiView.Subviews.All(x => x.RemoveFromSuperview);
【讨论】:
如果您想删除 UIView 上的所有子视图(此处为 yourView),请在单击按钮时编写此代码:
[[yourView subviews] makeObjectsPerformSelector: @selector(removeFromSuperview)];
【讨论】:
试试这个方法 swift 2.0
view.subviews.forEach { $0.removeFromSuperview() }
【讨论】:
forEach 的解决方案是在您之后添加的,我错过了。道歉。
使用 Swift UIView 扩展:
extension UIView {
func removeAllSubviews() {
for subview in subviews {
subview.removeFromSuperview()
}
}
}
【讨论】:
如果你使用的是 Swift,那么简单如下:
subviews.map { $0.removeFromSuperview }
它在理念上类似于 makeObjectsPerformSelector 方法,但类型安全性更高。
【讨论】:
map 应该不会产生副作用。另外,通过forEach 可以达到相同的结果。
为了从超级视图中删除所有子视图:
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 将是一个无限循环。这绝对是错误且不可用的代码。
为了删除所有子视图语法:
- (void)makeObjectsPerformSelector:(SEL)aSelector;
用法:
[self.View.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
此方法存在于 NSArray.h 文件中,并使用 NSArray(NSExtendedArray) 接口
【讨论】:
对于使用自动布局的 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 中设置的约束正在被清除。
【讨论】:
编辑:感谢cocoafan:NSView 和UIView 处理事情的方式不同,这使情况变得混乱。对于NSView(仅限桌面 Mac 开发),您可以简单地使用以下内容:
[someNSView setSubviews:[NSArray array]];
对于UIView(仅限iOS 开发),您可以安全地使用makeObjectsPerformSelector:,因为subviews 属性将返回子视图数组的副本:
[[someUIView subviews]
makeObjectsPerformSelector:@selector(removeFromSuperview)];
感谢Tommy 指出makeObjectsPerformSelector: 似乎在枚举subviews 数组时修改了它(它对NSView 起作用,但对UIView 不起作用)。
详情请见this SO question。
注意:使用这两种方法中的任何一种都会删除主视图包含的每个视图并释放它们,如果它们没有在其他地方保留。来自 Apple 在removeFromSuperview 上的文档:
如果receiver的superview不是nil,这个方法释放receiver。如果您打算重用视图,请务必在调用此方法之前保留它,并确保在使用完它或将其添加到另一个视图层次结构后适当地释放它。
【讨论】:
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]) 更简单