Pull to refresh UITableView without UITableViewController
Asked Answered
C

6

180

I'm trying to implement a pull to refresh feature in a UITableView within a UIViewController. I can't use a UITableViewController because I want the UITableView to be a smaller subview in the view controller, with some other stuff above it. I assume this is possible, but has anyone seen an implementation of it?

Craft answered 24/4, 2012 at 3:55 Comment(0)
M
470

Add a refresh control directly to a UITableView without using a UITableViewController:

override func viewDidLoad() {
    super.viewDidLoad()
    let refreshControl = UIRefreshControl()
    refreshControl.addTarget(self, action: #selector(refresh(_:)), for: .valueChanged)

    if #available(iOS 10.0, *) {
        tableView.refreshControl = refreshControl
    } else {
        tableView.backgroundView = refreshControl
    }
}

@objc func refresh(_ refreshControl: UIRefreshControl) {
    // Do your job, when done:
    refreshControl.endRefreshing()
}
Mundane answered 21/2, 2013 at 19:29 Comment(13)
Thanks, I believe UIRefreshControl is new. I think this is now the best way to do this.Craft
So, basically the refreshControl becomes the header of UITableView?Archduchy
Excellent and easy. It works for me when I tried it on a table view added to UIViewController on iOS 7.0.4.Fuller
has anyone had the problem where the control itself is not visible but otherwise seems to work fine?Notecase
Does not work properly if you have a positive top contentInset.Corymb
Table view seems to jump down unexpectedly once it "clicks". Not sure why yet.Vagary
I found that it needs to go in viewdidappear, not sure if that is an iOS 7 feature - I am yet to test it in iOS 8...Gary
@BobSpryn every figure out why it jumps down when it "clicks". Very annoying and making me consider just using a UITableViewController.Torsion
The refreshControl appears on top of the tableView. I fixed this by: tableView.insertSubview(refreshControl, atIndex: 0) instead of tableView.addSubview(refreshControl)Identic
the refresh control is not centeredHexane
If the initial swipe makes refreshControl jump over the tableView, use clear background color refreshControl.backgroundColor = [UIColor clearColor]; You still will see the tableViews background, since the refreshControl is not above it but init.Excessive
Be careful with this method if you have tableview headers. The headers will float below the refresh control, yet the tableview content will scroll above refresh control giving an odd effect. This does not occur when setting a UIRefreshControl on a UITableViewControllerPinzler
New way of using selector in Swift : #selector(YourClass.refresh)Plourde
U
13

Objective-C:

This is how you can implement pull to refresh for table view. Same as in the case of collection view. Just replace table view alloc with collection view.

UITableView *tableViewDemo  =  [[UITableView alloc]init];
tableViewDemo.frame = CGRectMake(0,0,self.view.frame.size.width,self.view.frame.size.height);
tableViewDemo.dataSource =  self;
tableViewDemo.delegate =  self;
[self.view addSubView: tableViewDemo];

UIRefreshControl *refreshController = [[UIRefreshControl alloc] init];
[refreshController addTarget:self action:@selector(handleRefresh:) forControlEvents:UIControlEventValueChanged];
[tableViewDemo addSubview:refreshController];

#pragma mark - Handle Refresh Method

-(void)handleRefresh : (id)sender
{
   NSLog (@"Pull To Refresh Method Called");
   [refreshController endRefreshing];
}
Unstring answered 9/8, 2016 at 9:5 Comment(2)
How does the obj-c version only have 9 upvotes when the swift version has >430?Parishioner
@ChaseRoberts, That one is answered on Feb 13, have a look at the edit history, originally it was in objective-c, Since at that time swift was new, every one was looking for swift version... stackoverflow.com/posts/15010646/revisionsSpiccato
J
4

This solution from @berik works fine but the UIController is displayed on top of the UITableViewController. The way to fix it is doing this change:

override func viewDidLoad() {
    let refreshControl = UIRefreshControl()
    refreshControl.addTarget(self, action: "refresh:", forControlEvents: .ValueChanged)
    tableView.backgroundView = refreshControl // <- THIS!!!
}

func refresh(refreshControl: UIRefreshControl) {
    // Do your job, when done:
    refreshControl.endRefreshing()
}
Judsen answered 4/11, 2015 at 14:19 Comment(1)
The refreshControl appears on top of the tableView for me, but your suggestion makes my refreshControl disappear, not appear below the tableView. I fixed this by: tableView.insertSubview(refreshControl, atIndex: 0) instead of tableView.addSubview(refreshControl)Identic
I
3

I've implemented EGORefreshTableHeaderView with a UIViewController and a simple table view, the trick is that a in the places where EGO takes a scroll view as a parameter, if you look the table view itself inherits from scroll view.

It only requires that and a few extra connections :)

Hope this helps.

Incised answered 24/4, 2012 at 3:58 Comment(0)
L
-1

It seems that if you create the UIRefreshControl inside the viewController's loadView method everything works fine. The UIRefreshControl behaves as it should. Tested with iOS 7.1 and iOS 8.2

Losse answered 31/3, 2015 at 6:44 Comment(0)
T
-1

I ended up using ODRefreshControl. It doesn't need any hack like the above tableView.backgroundView = refreshControl, works almost the same way, and gives a better looking UI.

Testy answered 25/5, 2017 at 2:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.