180
votes

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?

6

6 Answers

468
votes

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

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];
}
4
votes

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

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.

-1
votes

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

-1
votes

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.