7

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..")
    }
}
solarenqu
  • 804
  • 4
  • 19
  • 44

2 Answers2

16

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()
     }
}
Community
  • 1
  • 1
Lyndsey Scott
  • 37,080
  • 10
  • 92
  • 128
  • let subViews = self.scrollView.subviews for subview in subViews{ println("for removing...") if (subview is PostLineItem) { subview.removeFromSuperview() } else { println("not removing..") } } this is the solution! :) – solarenqu Jun 14 '15 at 16:36
  • @solarenqu Yes, that's even better since your added subviews are apparently all of type `PostLineItem`. – Lyndsey Scott Jun 14 '15 at 16:38
  • @LyndseyScott Can I create a UIView() to be added into the scrollview and all the subviews are added to this UIView, and then later when I want to remove all the subviews, I can just remove this UIView? – Joe Huang Dec 20 '15 at 11:49
  • Thanks for this! I was calling `view.removeFromSuperview()` and it wasn't working! Finally, I just iterated all the views on the window subviews, found the tag that I'd set, and removed it. – Jimbo Dec 08 '17 at 11:24
3

I stumbled about this problem today as well and would like to share my solution. You can remove all subviews of a view (and their subviews) with the following UIView extension in swift. In addition I attached a solution for removing all constraints the same way.

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

}

The first solution will keep all contraints, see Lyndseys answer. Be aware that this solution removes the whole hierarchy below the UIView. If you only want to remove specific subviews exchange or extend like this:

if !($0 is UILayoutSupport) && !($0 is PostLineItem)
masp
  • 350
  • 3
  • 10