33

I used the following code at a UICollectionViewController

override func viewDidLoad() {            

    self.collectionView!.alwaysBounceVertical = true
    let refresher = UIRefreshControl()
    refresher.addTarget(self, action: "refreshStream", forControlEvents: .ValueChanged)

    refreshControl = refresher
    collectionView!.addSubview(refreshControl!)
}

func refreshStream() {

    print("refresh")
    self.collectionView?.reloadData()

    refreshControl?.endRefreshing()

}

Now I need it to work with a UICollectionView inside a UIViewController and I googled for an hour now but can't get it working. I appreciate any help.

Fabio Berger
  • 1,908
  • 2
  • 22
  • 28
David Seek
  • 15,533
  • 14
  • 94
  • 125

6 Answers6

69

New swift code changed in calling action method you could do rewrite like this

@IBOutlet weak var collectionView: UICollectionView!

var refresher:UIRefreshControl!

override func viewDidLoad() {

   super.viewDidLoad()

    self.refresher = UIRefreshControl()
    self.collectionView!.alwaysBounceVertical = true
    self.refresher.tintColor = UIColor.red
    self.refresher.addTarget(self, action: #selector(loadData), for: .valueChanged)
    self.collectionView!.addSubview(refresher)
}

func loadData() {
   self.collectionView!.refreshControl.beginRefreshing()
   //code to execute during refresher
       .
       .
       .
   stopRefresher()         //Call this to stop refresher
 }

func stopRefresher() {
   self.collectionView!.refreshControl.endRefreshing()
 }
Nagarjun
  • 5,811
  • 5
  • 28
  • 47
  • Thank you, but "var refreshControl:UIRefreshControl!" need change to "var refresher:UIRefreshControl!" – Ego Slayer Aug 07 '16 at 15:50
  • 11
    rather than ```addSubview(refresher)```, the swift3 way of adding this refresher to a collection is: ```self.collectionView!.refreshControl = refresher self.collectionView!.refreshControl.beginRefreshing() self.collectionView!.refreshControl.endRefreshing()``` – Achintya Ashok Feb 22 '17 at 23:26
  • 3
    @KingChintz collectionView.refreshControl is only available in iOS10. addSubview works across more version. – Q Liu Mar 25 '17 at 06:13
  • Doesn't `let refresher = UIRefreshControl()` create a local instance of `UIRefreshControl` for `viewDidLoad` only? shouldn't it be `self.refresher = UIRefreshControl()` The code as is wouldn't run the stopRefresher correctly – Reza Shirazian Jun 17 '17 at 17:19
20
var refreshControl:UIRefreshControl!

override func viewDidLoad() {
    super.viewDidLoad()
      self.refreshControl = UIRefreshControl()
      self.refreshControl.attributedTitle = NSAttributedString(string: "Pull to refresh")
     self.refreshControl.addTarget(self, action: #selector(PricingPlansCollectionViewController.reload), for: .valueChanged)
      collectionView!.addSubview(refreshControl)
}

 func refresh(sender:AnyObject)
  {
    //DO 
  }
Romulo BM
  • 561
  • 6
  • 15
  • Your Code wants me to put in an semicolone betweet "ValueChanged) collectionView!" ----> Consecutive statements on a line must be separated by ';' – David Seek Feb 12 '16 at 13:43
  • You should be setting the refresh control object to the `refreshControl` property of your collectionView [per the docs](https://developer.apple.com/documentation/uikit/uirefreshcontrol) – Samy Aug 16 '19 at 05:31
16

Swift 5 solution

As @fishspy already mentioned, that's the way to put your collection view inside a view controller, but I'm gonna share also how to connect your refresh control to the collection view in a cleaner way.

Since iOS 10 there's a dedicated property for the refresh control. Apart of that, I'd also recommend to directly initialise your refresh control as a property, declaring it private and doing the following things:

@IBOutlet private weak var collectionView: UICollectionView!

private let refreshControl = UIRefreshControl()

override func viewDidLoad() {

    super.viewDidLoad()

    refreshControl.addTarget(self, action: #selector(didPullToRefresh(_:)), for: .valueChanged)
    collectionView.alwaysBounceVertical = true
    collectionView.refreshControl = refreshControl // iOS 10+
}

@objc
private func didPullToRefresh(_ sender: Any) {
    // Do you your api calls in here, and then asynchronously remember to stop the
    // refreshing when you've got a result (either positive or negative)
    refreshControl.endRefreshing()
}
Alessandro Francucci
  • 1,162
  • 13
  • 22
  • 1
    I've never seen an horizontal pull-to-refresh honestly, so no as far as I know – Alessandro Francucci Jun 17 '19 at 09:06
  • For anyone who needs this, I found an answer here: https://stackoverflow.com/questions/56614319/is-it-possible-to-add-a-drag-to-reload-horizontally-for-a-collection-view –  Jun 17 '19 at 17:14
13

From the storyboard, you need to link the collection view to the appropriate controller file, using Ctrl + Drag from the collection view object. It needs to be linked via an @IBOutlet.

Also, you should Ctrl + Drag from the collection view to the view controller object on the storyboard and select Data Source and Delegate so that the collection view is correctly linked.

Let me know if this helps or if I have misunderstood your situation.

fishspy
  • 146
  • 3
1
private let refreshControl = UIRefreshControl()

refreshControl.addTarget(self, action: #selector(youFunction), for: .valueChanged)
   
refreshControl.attributedTitle = NSAttributedString(string: "Fetching Data ...", attributes: nil)

DispatchQueue.main.async {
       self.refreshControl.endRefreshing()
       yourCollectionViewOrTableView.reloadData()
 }
Haseeb Javed
  • 856
  • 8
  • 10
1

For me, i had:

func setupCollectionView(){
      self.refreshControl = UIRefreshControl()
      self.refreshControl.attributedTitle = NSAttributedString(string: "Refreshing content...")
      self.refreshControl.addTarget(self, action: #selector(self.reload), for: .valueChanged)
      collectionView!.addSubview(refreshControl)
}

It still wasn't working (I believe i had constraints preventing it somehow), so i added:

collectionView.alwaysBounceVertical = true

then all was good. Just in case someone else is facing the same issue.

For a better understanding, the full implementation

@IBOutlet private weak var collectionView: UICollectionView!
let refreshControl = UIRefreshControl()

override func viewDidLoad() {
 super.viewDidLoad()
 setupCollectionView()
}

func setupCollectionView(){
      collectionView.delegate = self
      collectionView.dataSource = self
      collectionView.alwaysBounceVertical = true
      self.refreshControl = UIRefreshControl()
      self.refreshControl.attributedTitle = NSAttributedString(string: "Refreshing content...")
      self.refreshControl.addTarget(self, action: #selector(self.refresh), for: .valueChanged)
      collectionView!.addSubview(refreshControl)
}

 @objc func refresh(_ sender:AnyObject) {
    //do refreshing stuff
}
tendai
  • 457
  • 3
  • 12