UIRefreshControl - Pull To Refresh in iOS 7 [duplicate] - ios

This question already has answers here:
Pull To Refresh in iOS 7
(4 answers)
Closed 8 years ago.
I'm trying to get the pull to refresh feature on iOS 7 in my Table View. In my viewDidLoad, I have:
refreshControl = [[UIRefreshControl alloc] init];
[self.mytableView setContentOffset:CGPointMake(0, refreshControl.frame.size.height) animated:YES];
[refreshControl beginRefreshing];
[refreshControl addTarget:self action:#selector(refreshTable) forControlEvents:UIControlEventValueChanged];
I then run:
-(void)refreshTable {
[self.mytableView reloadData];
[refreshControl endRefreshing];
}
On iOS 6, this would mean that as you pull down on the table view, it would show the circular arrow that would get stretched out as you pull, and after pulled far enough, it would refresh. Right now, I see no circular arrow. What am I missing?

You do not have to explicitly set frame or start UIRefreshControl. If it is a UITableView or UICollectionView, it should work like a charm by itself. You do need to stop it though.
Here is how you code should look like:
- (void)viewDidLoad {
[super viewDidLoad];
refreshControl = [[UIRefreshControl alloc]init];
[refreshControl addTarget:self action:#selector(refreshTable) forControlEvents:UIControlEventValueChanged];
if (#available(iOS 10.0, *)) {
self.mytableView.refreshControl = refreshControl;
} else {
[self.mytableView addSubview:refreshControl];
}
}
In your refreshTable function, you need to stop it when you are done refreshing your data. Here is how it is going to look like:
- (void)refreshTable {
//TODO: refresh your data
[refreshControl endRefreshing];
[self.mytableView reloadData];
}
Please note that if you are refreshing your data asynchronously then you need to move endRefreshing and reloadData calls to your completion handler.

You forgot to attach the UIRefreshControl to your table view.
Change your viewDidLoad to
refreshControl = [[UIRefreshControl alloc]init];
[refreshControl addTarget:self action:#selector(refreshTable) forControlEvents:UIControlEventValueChanged];
[self setRefreshControl:refreshControl];
P.S. Your view controller should be a subclass of UITableViewController.

Related

iOS 10.0 UIRefreshControl not showing indicator

I am using a UITableView Which has a Pull down to refresh function but the spinner for pull down to refresh is not showing up when I call the [self.refreshControl beginRefreshing]
The above code is called inside the viewDidLoad cause the table is loading some data initially. The spinner works fine if I perform a pull down to refresh after the initial refresh. The title shows up but not the spinner.
Cant seem to solve this problem. It works fine on iOS 9.3.2 but not on iOS 10.
Here is the code I am using currently.
- (void)viewDidLoad
{
[super viewDidLoad];
[self setupView];
[self customSetup];
self.refreshControl = [[UIRefreshControl alloc] init];
self.refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:#"Updating Discounts..."];
[self.refreshControl addTarget:self action:#selector(reloadDeals) forControlEvents:UIControlEventValueChanged];
[self.refreshControl beginRefreshing];
[self.tableView setContentOffset:CGPointMake(0, -self.refreshControl.frame.size.height) animated:YES];
}
Thanks for your help in advance
before the code:
[refreshControl beginRefresh]
insert the code:
[refreshControl layoutIfNeeded]
Delaying call to refresh in viewDidLoad worked for me:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self.refreshControl beginRefreshing];
});
Same as #jpros answer but in swift
if #available(iOS 10.0, *) {
tableView.refreshControl = refreshControl
} else {
tableView.addSubview(refreshControl)
}
refreshControl.layoutIfNeeded()
refreshControl.beginRefreshing()
This is a known and reported bug in iOS 10.
Radar rdar://27468436
I'm not sure if there are any workarounds.
You need to call [self.view layoutIfNeeded] to fix it in iOS 10. For my case it was enough to put the call to viewDidLoad (I was using storyboard in that project). For other cases viewWillAppear fits better.
- (void)viewDidLoad
{
[super viewDidLoad];
[self.view layoutIfNeeded];
...
I was only able to fix this by calling, from viewDidLoad():
refreshControl.layoutIfNeeded()
In iOS10, we should add the UIRefreshControl using setRefreshControl of UITableView or UICollectionView.
if([self.tableView respondsToSelector:#selector(setRefreshControl:)]) {
[self.tableView setRefreshControl:self.refreshControl];
}
else {
[self.tableView addSubview:self.refreshControl];
}
[self.refreshControl layoutIfNeeded];
[self.refreshControl beginRefreshing];
If your refresh indicator is not showing try enabling Bounce Vertically in Interface Builder for table view or scroll view.

Proper pull to refresh

Is there any working pull to refresh lib?
PullToRefresh-master not works
SVPullToRefresh-master have errors
ODRefreshControl-master - not like I want
There are many Libraries available, but I recommend you to use UIRefreshControl.
Apple has introduced UIRefreshControl in iOS6. You can integrate it in your UITableViewController using
- (void)viewDidLoad {
[super viewDidLoad];
// Initialize Refresh Control
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
// Configure Refresh Control
[refreshControl addTarget:self action:#selector(refresh:) forControlEvents:UIControlEventValueChanged];
// Configure View Controller
[self setRefreshControl:refreshControl];
}
the refresh: method will trigger the update and you can stop it in your API callback using:
[(UIRefreshControl *)sender endRefreshing];

UIRefreshControl loading icon still loading

i implemented a UIRefreshControl for UICollectionView so that user can pull to refresh the content in UICollectionView. I am testing on the iPad simulator.
On the first attempt, I'm able to pull and refresh the content. However, I notice that the loading icon is still loading and doesn't stop. On my second attempt with the loading icon still showing, I pulled to refresh but it fails to call my selector(refreshCollectionAction).
Here is what I did:
-(void)viewDidLoad
{
// Do any additional setup after loading the view.
[super viewDidLoad];
// Register collectionView pull down to refresh
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:#selector(refreshCollectionAction)
forControlEvents:UIControlEventValueChanged];
[self.collectionView addSubview:refreshControl];
self.collectionView.alwaysBounceVertical = YES;
.....
}
-(void)refreshCollectionAction
{
NSLog(#"refresh collection action");
// Empty product Items Array
[[ProductStore getInstance] emptyProductInStore];
NSInteger numOfProductInStore = [[[ProductStore getInstance] allProductItems] count];
if (numOfProductInStore <= 0) {
// Fetch data from webservice and reload collectionView
[self fetchFeed:#""];
}
}
Am I missing some configurations? fetchFeed will request the data from web services. I have verified that the webservice still works.
[self.refreshControl endRefreshing];
Call this method at the end of any refresh operation (whether it was initiated programmatically or by the user) to return the refresh control to its default state. If the refresh control is at least partially visible, calling this method also hides it. If animations are also enabled, the control is hidden using an animation.
UIRefreshControl Class Reference
#interface ProductSearchViewController ()
#property(nonatomic)UIRefreshControl *refreshControl;
#end
- (void)viewDidLoad
{
// Do any additional setup after loading the view.
[super viewDidLoad];
// Register collectionView pull down to refresh
self.refreshControl = [[UIRefreshControl alloc] init];
[self.refreshControl addTarget:self action:#selector(refreshCollectionAction)
forControlEvents:UIControlEventValueChanged];
[self.collectionView addSubview:self.refreshControl];
self.collectionView.alwaysBounceVertical = YES;
...
}
-(void)refreshCollectionAction
{
NSLog(#"refresh collection action");
// Empty product Items Array
[[posProductStore getInstance] emptyProductInStore];
NSInteger numOfProductInStore = [[[posProductStore getInstance] allProductItems] count];
if (numOfProductInStore <= 0) {
[self fetchFeed:#""];
}
[self.refreshControl endRefreshing];
}
so basically i declare refreshControl as a class variable. as Neil mentioned, i added [self.refreshControl endRefreshing] at the end of method -(void)refreshCollectionAction.

Pull To Refresh in iOS 7

I'm trying to get the pull to refresh feature working properly on iOS 7 in my Table View. On viewDidLoad, I have:
self.refreshControl = [[UIRefreshControl alloc] init];
[self.refreshControl addTarget:self action:#selector(refreshInvoked:forState:) forControlEvents:UIControlEventValueChanged];
I then run:
-(void) refreshInvoked:(id)sender forState:(UIControlState)state {
// Refresh table here...
[_allEntries removeAllObjects];
[self.tableView reloadData];
[self refresh];
}
When the request that the refresh method invokes is done, in the didCompleteRequest code, I have:
[self.refreshControl endRefreshing];
On iOS 6, this would mean that as you pull down on the table view, it would show the circular arrow that would get stretched out as you pull, and after pulled far enough, it would refresh. Right now, though, I see no circular arrow, just a UIActivityIndicator. It also sometimes will work and sometimes will not. What am I missing?
To add UIRefreshControl in your UITableView...
1) in ViewDidLoad..
- (void)viewDidLoad
{
[super viewDidLoad];
//to add the UIRefreshControl to UIView
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:#"Please Wait..."]; //to give the attributedTitle
[refreshControl addTarget:self action:#selector(refresh:) forControlEvents:UIControlEventValueChanged];
[tblVideoView addSubview:refreshControl];
}
2) call related method to refresh the UITableView data...
- (void)refresh:(UIRefreshControl *)refreshControl
{
[self refreshTableData]; //call function you want
[refreshControl endRefreshing];
}
OR for Swift
let refreshControl : UIRefreshControl = UIRefreshControl.init()
refreshControl.attributedTitle = NSAttributedString.init(string: "Please Wait...")
refreshControl.addTarget(self, action: #selector(refresh), forControlEvents: UIControlEvents.ValueChanged)
feedTable.addSubview(refreshControl)
func refresh(refreshControl:UIRefreshControl){
self.refreshTableData()//call function you want
refreshControl.endRefreshing()
}
The 'UIActivityIndicator' that you are talking about is the new default appearance of a UIRefreshControl.
You pull down and as the circle completes it is showing how close to triggering a refresh you are.
You can remove/hide the default activity indicator, and add in your own images and animations.
There's also a certain threshold value (distance) that the table must be pulled past before the refresh is invoked.
Here's our tutorial for Custom Pull to Refresh controls (in objective-c and swift): http://www.jackrabbitmobile.com/design/ios-custom-pull-to-refresh-control/
Hope it helps, let me know if I can answer anything else
Update for swift
For TableView
- (void)viewDidLoad
{
let refreshControl = UIRefreshControl()
refreshControl.attributedTitle = NSAttributedString(string: "Please Wait..")
tableView.addSubview(refreshControl)
refreshControl.addTarget(self, action: #selector(refreshTable), forControlEvents: UIControlEventValueChanged)
}
- (void)refreshTable {
//Refresh Data here
//......
//Once all the data is fetched. If you are loading asynchronously add the below code inside the async block
refreshControl.endRefreshing()
[tableView reloadData];
}
For UITableViewController
In UITableViewController there is a default property called refreshControl which by default is nil. If you want just initialise the refreshControl and assign it.
let refreshControl = UIRefreshControl()
refreshControl.attributedTitle = NSAttributedString(string: "Please Wait..")
yourTableViewController.refreshControl = refreshControl

UITableView UIRefreshControl Does Not Show Its View The First Time

I have added the functionality of UIRefreshControl in my project that uses a UITableView. The app works by fetching entries from a web service to a tableview. Below is the code i have used to add UIRefreshControl:
- (void)viewDidLoad
{
[super viewDidLoad];
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
refreshControl.tintColor = [UIColor grayColor];
refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:#"Updating New Entries"];
[refreshControl addTarget:self action:#selector(pullToRefresh) forControlEvents:UIControlEventValueChanged];
self.refreshControl = refreshControl;
[self pullToRefresh];
}
- (void) pullToRefresh
{
counter = 1;
[self fetchEntriesNew:counter]; // My code for updating table view
[self performSelector:#selector(updateTable) withObject:nil afterDelay:2];
}
- (void)updateTable
{
[self.tableView reloadData];
[self.refreshControl endRefreshing];
}
Now if i pull to refresh, it refreshes by adding new entries if there are any and shows me the following view on top of the tableview:
Everything works great except when the app is launched or opened for the very first time, it does not show the view that i have showed in the above image, although it does refreshes the tableview. I want it to show the refresh control view every time it refreshes it. Can anyone point out what i am doing wrong? Thanks!
UPDATE: I have added [self refreshControl beginRefreshing] and the UIRefreshControl's spinner view is now showing but its above the first entry of the tableview. Can anyone point out how to correct it?
This problem had really puzzled me for a while.I found that 4-inch iOS devices don't have this problem, but 3.5-inch devices do.
I tried to find out the differences between the first time that the refreshControl beginRefreshing itself and when I operated a pull gesture.It's the pull operation.
And I checked Apple's document on UIRefreshControl.It says The control does not initiate the refresh operation directly. Instead, it sends the UIControlEventValueChanged event when a refresh operation should occur.
So I thought maybe I could add something to simulate a pull gesture to trigger refreshControl's showing.
[yourScrollView(or tableView) setContentOffset:CGPointMake(0.0f, -60.0f)
animated:YES];
[yourRefreshControl beginRefreshing];
It works!
PS. UIRefreshControl works with UIScrollView, too. [yourScrollView addSubview:yourRefreshControl] just works.
I would move your [self pullToRefresh] call to viewWillAppear instead of viewDidLoad.
There are two things that can be done to add UIRefreshControl in your tableview neither of them is added in your code
1. [self setRefreshControl:tableRefreshControl];
2. [self.m_TableView addSubview:tableRefreshControl];
Either add 1 or 2 if your class is subclass of UIViewController
If your class is subclass of UITableViewController then try to replace
self.refreshControl = refreshControl; with 2 line
before the code:
[refreshControl beginRefresh]
insert the code:
[refreshControl layoutIfNeeded]

Resources