删除所有子视图?

Ian*_*ink 312 subview ios

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

我怎样才能做到这一点?

e.J*_*mes 567

编辑:感谢cocoafan:这种情况因为事情NSViewUIView处理事情而变得混乱.对于NSView(仅限桌面Mac开发),您只需使用以下内容:

[someNSView setSubviews:[NSArray array]];
Run Code Online (Sandbox Code Playgroud)

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

[[someUIView subviews]
 makeObjectsPerformSelector:@selector(removeFromSuperview)];
Run Code Online (Sandbox Code Playgroud)

感谢Tommy指出在枚举时makeObjectsPerformSelector:似乎修改了subviews数组(它的目的是为了NSView,但不是为了UIView).

有关更多详细信息,请参阅此SO问题.

注意:使用这两种方法中的任何一种都将删除主视图包含的每个视图并释放它们,如果它们未在其他地方保留的话.从Apple关于removeFromSuperview的文档:

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

  • 你确定这是安全的吗?它在迭代时改变了列表,我无法在Apple的文档中找到明确的声明. (9认同)
  • @Tommy:这是一个好点.一些谷歌搜索出现了答案:`UIView`返回`subviews`可变数组的*副本*,所以这段代码正常.桌面上完全不同的故事,相同的代码会引发异常.请参阅http://stackoverflow.com/questions/4665179/behavior-difference-between-uiview-subviews-and-nsview-subviews (8认同)
  • Xamarin方式:someUIView.Subviews.All(p => p.RemoveFromSuperview); (4认同)
  • UIView没有响应setSubviews :,是吗? (3认同)
  • @BenoitJadinon - 不会编译 - 你似乎意味着滥用All来执行ForEach,所以`someUIView.Subviews.All(v => {v.RemoveFromSuperview(); return true;});`.恕我直言清洁你说的意思:`someUIView.Subviews.ToList().ForEach(v => v.RemoveFromSuperview());`. (3认同)

Mat*_*gan 171

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

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

  • @taylorcressy你应该说"可读性比保存击键更重要"而不是"可读性>保存击键"然后你的评论会更具可读性.:-) (33认同)
  • @Frade他做的更清晰,更冗长.详细和可读性>保存击键 (4认同)
  • 为什么不!?`for(UIView*v in [self.view subviews])`更容易 (2认同)

Jee*_*hut 110

Swift中,您可以使用这样的功能方法:

view.subviews.forEach { $0.removeFromSuperview() }
Run Code Online (Sandbox Code Playgroud)

作为比较,命令式方法如下所示:

for subview in view.subviews {
    subview.removeFromSuperview()
}
Run Code Online (Sandbox Code Playgroud)

这些代码片段仅适用于iOS/tvOS,但macOS上的情况略有不同.

  • 它不起作用,因为函数返回一个值,这只会丢弃`.map`的结果.这是一个纯粹的副作用,并且更好地处理如下:`view.subviews.forEach(){$ 0.removeFromSuperview()}` (8认同)
  • ```(子视图为[UIView]).map {$ 0.removeFromSuperview()}``` (4认同)

小智 13

如果要删除UIView(此处yourView)上的所有子视图,请在按下按钮时编写此代码:

[[yourView subviews] makeObjectsPerformSelector: @selector(removeFromSuperview)];
Run Code Online (Sandbox Code Playgroud)

  • 欢迎来到Stack Overflow!您是否会考虑添加一些叙述来解释为什么这段代码有效,以及是什么使它成为问题的答案?这对提出问题的人以及其他任何人来说非常有帮助.此外,已经接受的答案包括与此基本相同的代码. (12认同)
  • 这可能比接受的答案更有帮助:它是完全相同的.为什么写这个? (5认同)

Dan*_*iel 8

删除所有子视图时,最好在数组末尾开始删除并继续删除,直到到达开头.这可以通过以下两行代码完成:

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

SWIFT 1.2

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

或(效率低下,但更具可读性)

for subview in mySuperView.subviews.reverse() {
    subview.removeFromSuperview()
}
Run Code Online (Sandbox Code Playgroud)

注意

您应该删除子视图是正常的顺序,因为这可能会导致崩溃,如果一个UIView实例被删除之前,removeFromSuperview消息已经被发送到阵列的所有对象.(显然,删除最后一个元素不会导致崩溃)

因此,代码

[[someUIView subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
Run Code Online (Sandbox Code Playgroud)

应该被使用.

Apple文档中引用makeObjectsPerformSelector:

向数组中的每个对象发送由给定选择器标识的消息,从第一个对象开始并继续通过数组到最后一个对象.

(为此目的,这将是错误的方向)


Wil*_* Hu 5

试试这种方式 swift 2.0

view.subviews.forEach { $0.removeFromSuperview() }
Run Code Online (Sandbox Code Playgroud)

  • 你没看到我更早的回答日期吗?为什么不将我的答案链接粘贴到该答案中? (2认同)

小智 5

view.subviews.forEach { $0.removeFromSuperview() }
Run Code Online (Sandbox Code Playgroud)

  • 虽然此代码可以回答问题,但提供有关如何和/或为何解决问题的附加上下文将提高​​答案的长期价值。 (2认同)