Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIRefreshControl on viewDidLoad

I'm using the following code to create a UIRefreshControl:

- (void) viewDidLoad {     [super viewDidLoad];      UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];     [refreshControl addTarget:self action:@selector(doLoad) forControlEvents:UIControlEventValueChanged];     self.refreshControl = refreshControl; }  - (void) doLoad {     dispatch_async(dispatch_get_global_queue(0, 0), ^{             // Instead of sleeping, I do a webrequest here.             [NSThread sleepForTimeInterval: 5];              dispatch_async(dispatch_get_main_queue(), ^{                 [tableView reloadData];                 [self.refreshControl endRefreshing];             });     }); } 

It works great. If I navigate to my view, drag the table, the code runs and the data displays.

However, what I would like to do is have the view in the 'loading' state as soon as it appears (that way the user knows something is going on). I have tried adding the following:

- (void)viewDidAppear:(BOOL)animated {     [super viewDidAppear:animated];     [self.refreshControl beginRefreshing]; } 

But it does not seem to work. When I navigate to the view, it looks like a regular view (refresh control is not visible), plus when I try to pull the refresh control, it never finished loading.

Obviously I'm going about this the wrong way. Any suggestions on how I should handle this?

like image 981
Kyle Avatar asked Jul 29 '13 17:07

Kyle


2 Answers

Try this:

- (void) viewWillAppear: (BOOL) animated {     [super viewWillAppear: animated];      self.tableView.contentOffset = CGPointMake(0, -self.refreshControl.frame.size.height);     [self.refreshControl beginRefreshing];          // kick off your async refresh!     [self doLoad]; } 

Remember to call endRefreshing at some point!

EDIT to add full working sample:

This sample view controller, built and run in iOS6.1 as the root viewcontroller starts with the UIRefreshControl already visible and animating when the app launches.

TSTableViewController.h

@interface TSTableViewController : UITableViewController @end 

TSTableViewController.m

#import "TSTableViewController.h"  @implementation TSTableViewController {     NSMutableArray*    _dataItems; }  - (void) viewDidLoad {     [super viewDidLoad];      self.refreshControl = [UIRefreshControl new];      [self.refreshControl addTarget: self                             action: @selector( onRefresh: )                   forControlEvents: UIControlEventValueChanged]; }  - (void) viewWillAppear:(BOOL)animated {     [super viewWillAppear: animated];      self.tableView.contentOffset = CGPointMake(0, -self.refreshControl.frame.size.height);      [self.refreshControl beginRefreshing];     [self onRefresh: nil]; }  - (void) onRefresh: (id) sender {     double delayInSeconds = 2.0;     dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));     dispatch_after(popTime, dispatch_get_main_queue(), ^(void){          _dataItems = [NSMutableArray new];          for ( int i = 0 ; i < arc4random() % 100 ; i++ )         {             CFUUIDRef uuid = CFUUIDCreate( NULL );              [_dataItems addObject: CFBridgingRelease(CFUUIDCreateString( NULL, uuid)) ];              CFRelease( uuid );         }          [self.refreshControl endRefreshing];          [self.tableView reloadData];     }); }  #pragma mark - Table view data source  - (NSInteger) numberOfSectionsInTableView: (UITableView *) tableView {     return 1; }  - (NSInteger) tableView:(UITableView *) tableView numberOfRowsInSection: (NSInteger) section {     return _dataItems.count; }  - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {     UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault                                                    reuseIdentifier: nil];      cell.textLabel.text = [_dataItems objectAtIndex: indexPath.row];      return cell; }  @end 
like image 135
TomSwift Avatar answered Oct 02 '22 16:10

TomSwift


Manually modifying the contentOffset is insecure and wrong and can lead to unexpected behavior in some cases. This solution works without touching the contentOffset at all:

func showRefreshControl(show: Bool) {     if show {         refreshControl?.beginRefreshing()         tableView.scrollRectToVisible(CGRectMake(0, 0, 1, 1), animated: true)     } else {         refreshControl?.endRefreshing()     } } 
like image 20
Era Avatar answered Oct 02 '22 17:10

Era