I\'ve setup a UIRefreshControl in my UITableViewController (which is inside a UINavigationController) and it works as expected (i.e. pull down fires the correct event). Howe
Here is Swift 3 and later extension that shows spinner as well as animate it.
import UIKit
extension UIRefreshControl {
func beginRefreshingWithAnimation() {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {
if let scrollView = self.superview as? UIScrollView {
scrollView.setContentOffset(CGPoint(x: 0, y: scrollView.contentOffset.y - self.frame.height), animated: true)
}
self.beginRefreshing()
}
}
}
For Swift 5, for me the only thing missing was to call refreshControl.sendActions(.valueChanged)
. I made an extension to make it more cleaner.
extension UIRefreshControl {
func beginRefreshingManually() {
if let scrollView = superview as? UIScrollView {
scrollView.setContentOffset(CGPoint(x: 0, y: scrollView.contentOffset.y - frame.height), animated: false)
}
beginRefreshing()
sendActions(for: .valueChanged)
}
}
I use the same technique for show user "data is update" visual sign. A result user bring app from background and feeds/lists will be update with UI like users pull tables to refresh himself. My version contain 3 things
1) Who send "wake up"
- (void)applicationDidBecomeActive:(UIApplication *)application {
[[NSNotificationCenter defaultCenter] postNotificationName:kNotificationHaveToResetAllPages object:nil];
}
2) Observer in UIViewController
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(forceUpdateData) name:kNotificationHaveToWakeUp:nil];
}
3)The protocol
#pragma mark - ForcedDataUpdateProtocol
- (void)forceUpdateData {
self.tableView.contentOffset = CGPointZero;
if (self.refreshControl) {
[self.refreshControl beginRefreshing];
[self.tableView setContentOffset:CGPointMake(0, -self.refreshControl.frame.size.height) animated:YES];
[self.refreshControl performSelector:@selector(endRefreshing) withObject:nil afterDelay:1];
}
}
It's works perfect to me:
Swift 3:
self.tableView.setContentOffset(CGPoint(x: 0, y: -self.refreshControl!.frame.size.height - self.topLayoutGuide.length), animated: true)
tested on Swift 5
use this in viewDidLoad()
fileprivate func showRefreshLoader() {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {
self.tableView.setContentOffset(CGPoint(x: 0, y: self.tableView.contentOffset.y - (self.refreshControl.frame.size.height)), animated: true)
self.refreshControl.beginRefreshing()
}
}
Here's a Swift extension using the strategies described above.
extension UIRefreshControl {
func beginRefreshingManually() {
if let scrollView = superview as? UIScrollView {
scrollView.setContentOffset(CGPoint(x: 0, y: scrollView.contentOffset.y - frame.height), animated: true)
}
beginRefreshing()
}
}