Swift 从超级视图中删除子视图

Posted

技术标签:

【中文标题】Swift 从超级视图中删除子视图【英文标题】:Swift remove subviews from superview 【发布时间】:2015-06-14 15:54:22 【问题描述】:

我有一个scrollView,我向它添加了一个refreshcontroll。

self.refreshControl = UIRefreshControl()
self.refreshControl.attributedTitle = NSAttributedString(string: "Frissítéshez húzzad! :)")
self.refreshControl.addTarget(self, action: "refresh:", forControlEvents: UIControlEvents.ValueChanged)
self.scrollView.addSubview(refreshControl)

在刷新方法中,我必须从滚动视图中删除所有子视图,然后重新填充滚动视图..

self.refreshControl = UIRefreshControl()
self.refreshControl.attributedTitle = NSAttributedString(string: "Frissítéshez húzzad! :)")
self.refreshControl.addTarget(self, action: "refresh:", forControlEvents: UIControlEvents.ValueChanged)
self.scrollView.addSubview(refreshControl)

在我尝试拉动后,我的滚动视图获得了新数据,但它不再有 refreshcontroll。我认为这是因为当我从滚动视图中删除子视图时,我也从中删除了 refreshcontroll。 (如果我在刷新方法中再次添加 refreshcontroll,我的滚动视图将再次具有 refreshconroll)但是还有另一个问题。刷新我的滚动视图后向下移动..我附上了图片:

这就是我删除子视图的方式:

func refresh(sender:AnyObject)

    //remove all subviews from scrollview..
    let subViews = self.scrollView.subviews
    for subview in subViews
        println("for removing...")
        subview.removeFromSuperview()
    

    println("refresh called..")
    UIApplication.sharedApplication().applicationIconBadgeNumber = 0
    //remove all elements from the array
    tstFrames.removeAll(keepCapacity: false)
    //refresh data from webservice and adding it to tstFrames Array
    wsServiceFeedTst()
    //adding items to the scrollview from tstFramesArray
    addPosts()
    self.refreshControl.endRefreshing()


这是刷新前滚动视图的样子:

这是刷新后的样子:

有人能帮我解释一下为什么会下降吗?

谢谢!

谢谢,解决办法:

let subViews = self.scrollView.subviews
for subview in subViews
    println("for removing...")
    if (subview is PostLineItem) 
        subview.removeFromSuperview()
    
    else 
        println("not removing..")
    

【问题讨论】:

你能发布你用来删除子视图的代码吗? 我问是因为您可能同时删除了刷新控制器和布局约束... 谢谢!检查我更新的问题..布局约束也是子视图吗? :) 【参考方案1】:

通过删除所有子视图,您还可以删除您明确添加的子视图以外的子视图,例如刷新视图和布局约束。

(为了回答 cmets 的问题,布局约束实际上可以是子视图。我在这里解释了如何删除除布局约束之外的所有子视图:https://***.com/a/27281242/2274694。)

一般而言,我建议您将代码更改为更具体,以便仅删除您添加的视图。例如,您可以在 addPosts 方法中添加的子视图中添加标签:

post.tag = 1000

然后只删除refresh:中带有该标签的子视图:

let subViews = self.scrollView.subviews
for subview in subViews
    if subview.tag == 1000 
        subview.removeFromSuperview()
    

以确保您不会删除您自己未明确添加的任何子视图。

编辑:原来 OP 添加的子视图都是自定义类型 PostLineItem,所以标签是不必要的,因为我们可以删除所有 PostLineItems:

for subview in self.view.subviews 
    if subview is PostLineItem 
        subview.removeFromSuperview()
     

【讨论】:

让 subViews = self.scrollView.subviews for subviews in subViews println("for remove...") if (subview is PostLineItem) subview.removeFromSuperview() else println("not删除..") 这就是解决方案! :) @solarenqu 是的,这更好,因为您添加的子视图显然都是PostLineItem 类型。 @LyndseyScott 我可以创建一个 UIView() 以添加到滚动视图中并将所有子视图添加到此 UIView,然后当我想删除所有子视图时,我可以删除它界面视图? 谢谢!我打电话给view.removeFromSuperview(),但它不起作用!最后,我只是迭代了窗口子视图上的所有视图,找到了我设置的标签,并将其删除。【参考方案2】:

我今天也偶然发现了这个问题,并想分享我的解决方案。您可以使用以下 UIView 扩展在 swift 中删除视图的所有子视图(及其子视图)。此外,我附上了一个以相同方式移除所有约束的解决方案。

extension UIView 

  // Recursive remove subviews and constraints
  func removeSubviews() 
    self.subviews.forEach(
        if !($0 is UILayoutSupport) 
            $0.removeSubviews()
            $0.removeFromSuperview()
        
    )

  

  // Recursive remove subviews and constraints
  func removeSubviewsAndConstraints() 
    self.subviews.forEach(
        $0.removeSubviewsAndConstraints()
        $0.removeConstraints($0.constraints)
        $0.removeFromSuperview()
    )
  


第一个解决方案将保留所有约束,请参阅 Lyndseys 的回答。请注意,此解决方案会删除 UIView 下方的整个层次结构。如果您只想删除特定的子视图交换或像这样扩展:

if !($0 is UILayoutSupport) && !($0 is PostLineItem)

【讨论】:

以上是关于Swift 从超级视图中删除子视图的主要内容,如果未能解决你的问题,请参考以下文章

从超级视图中删除视图时出错

如何使 xib 子视图与 Swift 中的超级视图交互?

从超级视图中删除当前视图

UIView 即使在开始从超级视图中删除后也会重新出现

iOS 从超级视图中删除对象会破坏自动布局并禁用滚动视图

添加删除的子视图 Swift 3 iOS