UIRefreshControl without UITableViewController

2018-12-31 23:07发布

Just curious, as it doesn't immediately seem possible, but is there a sneaky way to leverage the new iOS 6 UIRefreshControl class without using a UITableViewController subclass?

I often use a UIViewController with a UITableView subview and conform to UITableViewDataSource and UITableViewDelegate rather than using a UITableViewController outright.

12条回答
回忆,回不去的记忆
2楼-- · 2018-12-31 23:53

What you would try is use container view inside ViewController you are using. you can define clean UITableViewController subclass with dedicated tableview and place that in the ViewController.

查看更多
情到深处是孤独
3楼-- · 2018-12-31 23:55

Keller's first suggestion causes a strange bug in iOS 7 where the inset of the table is increased after the view controller reappears. Changing to the second answer, using the uitableviewcontroller, fixed things for me.

查看更多
骚的不知所云
4楼-- · 2019-01-01 00:02

For Swift 2.2 .

First make UIRefreshControl() .

var refreshControl : UIRefreshControl!

In your viewDidLoad() method add:

refreshControl = UIRefreshControl()
    refreshControl.attributedTitle = NSAttributedString(string: "Refreshing..")
    refreshControl.addTarget(self, action: #selector(YourUIViewController.refresh(_:)), forControlEvents: UIControlEvents.ValueChanged)
    self.tableView.addSubview(refreshControl)

And make refresh function

func refresh(refreshControl: UIRefreshControl) {

    // do something ...

    // reload tableView
    self.tableView.reloadData()

    // End refreshing
    refreshControl.endRefreshing()
}
查看更多
高级女魔头
5楼-- · 2019-01-01 00:04

Try delaying the call to the refreshControl -endRefresh method by a fraction of a second after the tableView reloads its contents, either by using NSObject's -performSelector:withObject:afterDelay: or GCD's dispatch_after.

I created a category on UIRefreshControl for this:

@implementation UIRefreshControl (Delay)

- (void)endRefreshingAfterDelay:(NSTimeInterval)delay {
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC));
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        [self endRefreshing];
    });
}

@end

I tested it and this also works on Collection Views. I've noticed that a delay as small as 0.01 seconds is enough:

// My data refresh process here while the refresh control 'isRefreshing'
[self.tableView reloadData];
[self.refreshControl endRefreshingAfterDelay:.01];
查看更多
回忆,回不去的记忆
6楼-- · 2019-01-01 00:06

Adding the refresh control as a subview creates an empty space above section headers.

Instead, I embedded a UITableViewController into my UIViewController, then changed my tableView property to point towards the embedded one, and viola! Minimal code changes. :-)

Steps:

  1. Create a new UITableViewController in Storyboard and embed it into your original UIViewController
  2. Replace @IBOutlet weak var tableView: UITableView! with the one from the newly embedded UITableViewController, as shown below

class MyViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    weak var tableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()

        let tableViewController = self.childViewControllers.first as! UITableViewController
        tableView = tableViewController.tableView
        tableView.dataSource = self
        tableView.delegate = self

        // Now we can (properly) add the refresh control
        let refreshControl = UIRefreshControl()
        refreshControl.addTarget(self, action: "handleRefresh:", forControlEvents: .ValueChanged)
        tableViewController.refreshControl = refreshControl
    }

    ...
}
查看更多
心情的温度
7楼-- · 2019-01-01 00:09

It turns out you can use the following when you use a UIViewController with a UITableView subview and conform to UITableViewDataSource and UITableViewDelegate:

self.refreshControl = [[UIRefreshControl alloc]init];
[self.refreshControl addTarget:self action:@selector(refresh:) forControlEvents:UIControlEventValueChanged];
查看更多
登录 后发表回答