Swift remove subviews from superview

solarenqu picture solarenqu · Jun 14, 2015 · Viewed 25.1k times · Source

i have a scrollView, and i added a refreshcontroll to it.

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)

in the refresh method i have to remove all subviews from the scrollview, then repopulate the scrollview..

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)

after i try to pull, my scrollview get new data but it's don't have anymore refreshcontroll. i think it is because when i removing subviews from my scrollview i also remove the refreshcontroll from it. (if i add the refreshcontroll again in my refresh method my scrollview will have refreshconroll again) But there is another problem. After refreshing my scrollview moving down.. i attached to pictures:

This is how i remove the subiews:

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()

}

This is how scrollview look like before refreshing: enter image description here

An this is how it looks like after refreshing: enter image description here

could anybody help me about why is this moving down?

Thank you!

Thank you, this is the solution:

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

Answer

Lyndsey Scott picture Lyndsey Scott · Jun 14, 2015

By removing all subviews, you can also be removing subviews other than the ones you explicitly added, like the refresh view and layout constraints.

(And to answer your question from the comments, layout constraints can in fact be subviews. I explain how to remove all subviews except layout constraints here: https://stackoverflow.com/a/27281242/2274694.)

In general, I recommend changing your code to be more specific such that only the views you've added are removed. For example, you could add a tag to the subviews you add in your addPosts method:

post.tag = 1000

then remove only the subviews with that tag in refresh::

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

to ensure that you don't remove any subviews you haven't explicitly added yourself.

Edit: It turns out the OP's added subviews are all of custom type PostLineItem so the tags are unnecessary since we can just remove all the PostLineItems instead:

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