I have set up a refresh control but its not working, I did try to reloadData() in tableView , ill provide my code if there is a mistake :(
Its not reloading nothing in tableView
#objc private func refreshListData(_ sender: Any) {
self.monitorimiTableView.reloadData()
self.pullControl.endRefreshing()
}
override func viewDidLoad() {
super.viewDidLoad()
pullControl.bounds = CGRect(x: 0, y: 50, width: pullControl.bounds.size.width, height: pullControl.bounds.size.height)
pullControl.attributedTitle = NSAttributedString(string: "")
pullControl.addTarget(self, action: #selector(refreshListData(_:)), for: .valueChanged)
}
if #available(iOS 10.0, *) {
tableView.refreshControl = pullControl
} else {
tableView.addSubview(pullControl)
}
let refreshControl = UIRefreshControl()
override func viewDidLoad() {
super.viewDidLoad()
refreshControl.attributedTitle = NSAttributedString(string: "Pull to refresh")
refreshControl.addTarget(self, action: #selector(self.refresh(_:)), for: .valueChanged)
tableView.addSubview(refreshControl) // not required when using UITableViewController
}
#objc func refresh(_ sender: AnyObject) {
// Code to refresh table view
refreshControl.endRefreshing()
}
Related
While pulling down to refresh, the controller target method is not being called.
Why is this issue happening?
override func viewDidLoad() {
super.viewDidLoad()
scrollview.alwaysBounceVertical = true
scrollview.bounces = true
refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action: #selector(didPullToRefresh), for: .valueChanged)
self.scrollview.addSubview(refreshControl)
}
#objc func didPullToRefresh() {
print("Refersh")
// For End refrshing
refreshControl.endRefreshing()
}
iOS 10 > UIScrollView has a refreshControl property. This refreshControl will appear when you create a UIRefereshControl and assign it to this property. No need to add UIRefereshControl as a subview for scroll.
func configureRefreshControl () {
// Add the refresh control to your UIScrollView object.
myScrollingView.refreshControl = UIRefreshControl()
myScrollingView.refreshControl?.addTarget(self, action:
#selector(handleRefreshControl),
for: .valueChanged)
}
#objc func handleRefreshControl() {
// Update your content…
// Dismiss the refresh control.
DispatchQueue.main.async {
self.myScrollingView.refreshControl?.endRefreshing()
}
}
I've a VC containing Table View. I've implemented pull to refresh on table view and activity indicator on view. On pull to refresh table view flickers as it looks like it has finished refreshing and reloads while I pull down and keep holding the table view. I'm not sure where it's going wrong. Following is my code. How to I implement it correctly?
class MyViewController: CustomVC {
override func viewDidLoad() {
super.viewDidLoad()
self.addRefreshControl(to: tableView)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
self.view.activityStartAnimating()
self.tableView.isHidden = true
loadContent(isRefresh: false)
}
private func loadContent(isRefresh: Bool) {
fetchContent() { (result, error) in
// ....
if isRefresh {
self.refreshControl.endRefreshing()
} else {
self.view.activityStopAnimating()
}
// ...
self.tableView.reloadData()
self.tableView.isHidden = false
}
}
// Pull to refresh
override func fetchDataForRefresh() {
loadContent(isRefresh: true)
}
}
Custom VC class
class CustomVC: UIViewController {
lazy var refreshControl: UIRefreshControl = {
let refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action: #selector(refresh(_:)), for: UIControl.Event.valueChanged)
refreshControl.transform = CGAffineTransform(scaleX: 0.87, y: 0.87)
return refreshControl
}()
override func viewDidLoad() {
super.viewDidLoad()
}
func addRefreshControl(to tableView: UITableView) {
if #available(iOS 10.0, *) {
tableView.refreshControl = refreshControl
} else {
tableView.addSubview(refreshControl)
}
tableView.indicatorStyle = .white
}
#objc func refresh(_ refreshControl: UIRefreshControl) {
fetchDataForRefresh()
}
func fetchDataForRefresh() {
}
}
Fetch Content
func fetchContent() {
// .....
DispatchQueue.main.async {
completed(resultData,nil)
return
}
//....
}
Try this technique
func setupRefreshControl() {
refreshControl = UIRefreshControl()
refreshControl?.addTarget(self, action: #selector(refreshData), for: .valueChanged)
tableView?.refreshControl = refreshControl
}
When you finished fetching your data:
DispatchQueue.main.async {
self.refreshControl?.perform(#selector(UIRefreshControl.endRefreshing), with: nil, afterDelay: 0)
self.tableView.reloadData()
}
Please note I have access to refreshControl because I'm inside a UITableViewController but you can easily add it in a UIViewController as well.
Remove the if refresh else ... from your code and put your reload your UITableView and endRefreshing on the main thread as I mentioned above
I have a scrollable content in my view. I want to add pull to refresh in it. I try to add but action is not triggered.
I tried many couple of ways & re-search also but none of it worked for me. I have iOS 10 as minimum deployment target.
Try1:
let refreshControl = UIRefreshControl()
self.scl_view.alwaysBounceVertical = true
refreshControl.addTarget(self, action: #selector(pullToRefresh(_:)), for: .valueChanged)
scl_view.addSubview(refreshControl)
Try2:
let refreshControl = UIRefreshControl()
self.scl_view.alwaysBounceVertical = true
refreshControl.addTarget(self, action: #selector(pullToRefresh(_:)), for: .valueChanged)
scl_view.refreshControl = refreshControl
//MARK:- Refresh control
#objc func pullToRefresh(_ refreshControl: UIRefreshControl) {
// Update your conntent here
self.setupData()
//refreshControl.endRefreshing()
}
select your tablviewcontroller
goto inspector
find refreshing select enabled
goto document outline and select refresh control
control drag or right click(hold) drag to your controller file and call function on it to refresh data
it is not available on tableview
var refreshControl = UIRefreshControl()
override func viewDidLoad() {
super.viewDidLoad()
collectionView.delegate = self
collectionView.dataSource = self
// Add Refresh Control to collection View
if #available(iOS 10.0, *) {
collectionView.refreshControl = refreshControl
} else {
collectionView.addSubview(refreshControl)
}
refreshControl.tintColor = UIColor(red:0.25, green:0.72, blue:0.85, alpha:1.0)
// Configure Refresh Control
refreshControl.addTarget(self, action: #selector(fetchData(_:)), for: .valueChanged)
}
#objc private func fetchData(_ sender: Any) {
DispatchQueue.main.async {
//Fuction which you want to call
self.refreshControl.endRefreshing()
}
}
Why doesn't this work in swift 3 ? It crashes at runtime saying:
'-[my_app_name.displayOtherAppsCtrl tap:]: unrecognized selector sent
to instance 0x17eceb70'
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Register cell classes
//self.collectionView!.register(ImageCell.self, forCellWithReuseIdentifier: reuseIdentifier)
// Do any additional setup after loading the view.
let lpgr = UITapGestureRecognizer(target: self, action: Selector("tap:"))
lpgr.delegate = self
collectionView?.addGestureRecognizer(lpgr)
}
func tap(gestureReconizer: UITapGestureRecognizer) {
if gestureReconizer.state != UIGestureRecognizerState.ended {
return
}
let p = gestureReconizer.location(in: self.collectionView)
let indexPath = self.collectionView?.indexPathForItem(at: p)
if let index = indexPath {
//var cell = self.collectionView?.cellForItem(at: index)
// do stuff with your cell, for example print the indexPath
print(index.row)
} else {
print("Could not find index path")
}
}
Selector("tap:") should now be written as #selector(tap(gestureReconizer:))
Also, you should declare tap as func tap(_ gestureRecognizer: UITapGestureRecognizer) as per the new Swift API Guidelines in which case your selector would then become #selector(tap(_:)).
In Swift 3 it works like this:
#IBOutlet var myView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action:#selector(handleTap))
myView.addGestureRecognizer(tap)
}
func handleTap() {
print("tapped")
}
Swift 3 came with new syntax so instead of using Selector("tap:"), #selector(tap(gestureReconizer:)) is
Swift 3:
class MYPTempController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let btn = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
view.addSubview(btn)
btn.addTarget(self, action: #selector(MYPTempController.btnClick), for: .touchUpInside)
}
#objc fileprivate func btnClick() {
print("--click--")
}
}
//带参数
btn.addTarget(self, action: #selector(MYPTempController.btnClick(_:)), for: .touchUpInside)
//监听方法
func btnClick(_ sender: UIButton) {
print("--click--")
}
I used the following code at a UICollectionViewController
override func viewDidLoad() {
self.collectionView!.alwaysBounceVertical = true
let refresher = UIRefreshControl()
refresher.addTarget(self, action: "refreshStream", forControlEvents: .ValueChanged)
refreshControl = refresher
collectionView!.addSubview(refreshControl!)
}
func refreshStream() {
print("refresh")
self.collectionView?.reloadData()
refreshControl?.endRefreshing()
}
Now I need it to work with a UICollectionView inside a UIViewController and I googled for an hour now but can't get it working.
I appreciate any help.
New swift code changed in calling action method you could do rewrite like this
#IBOutlet weak var collectionView: UICollectionView!
var refresher:UIRefreshControl!
override func viewDidLoad() {
super.viewDidLoad()
self.refresher = UIRefreshControl()
self.collectionView!.alwaysBounceVertical = true
self.refresher.tintColor = UIColor.red
self.refresher.addTarget(self, action: #selector(loadData), for: .valueChanged)
self.collectionView!.addSubview(refresher)
}
#objc func loadData() {
self.collectionView!.refreshControl.beginRefreshing()
//code to execute during refresher
.
.
.
stopRefresher() //Call this to stop refresher
}
func stopRefresher() {
self.collectionView!.refreshControl.endRefreshing()
}
Swift 5 solution
As #fishspy already mentioned, that's the way to put your collection view inside a view controller, but I'm gonna share also how to connect your refresh control to the collection view in a cleaner way.
Since iOS 10 there's a dedicated property for the refresh control. Apart of that, I'd also recommend to directly initialise your refresh control as a property, declaring it private and doing the following things:
#IBOutlet private weak var collectionView: UICollectionView!
private let refreshControl = UIRefreshControl()
override func viewDidLoad() {
super.viewDidLoad()
refreshControl.addTarget(self, action: #selector(didPullToRefresh(_:)), for: .valueChanged)
collectionView.alwaysBounceVertical = true
collectionView.refreshControl = refreshControl // iOS 10+
}
#objc
private func didPullToRefresh(_ sender: Any) {
// Do you your api calls in here, and then asynchronously remember to stop the
// refreshing when you've got a result (either positive or negative)
refreshControl.endRefreshing()
}
var refreshControl:UIRefreshControl!
override func viewDidLoad() {
super.viewDidLoad()
self.refreshControl = UIRefreshControl()
self.refreshControl.attributedTitle = NSAttributedString(string: "Pull to refresh")
self.refreshControl.addTarget(self, action: #selector(PricingPlansCollectionViewController.reload), for: .valueChanged)
collectionView!.addSubview(refreshControl)
}
func refresh(sender:AnyObject)
{
//DO
}
From the storyboard, you need to link the collection view to the appropriate controller file, using Ctrl + Drag from the collection view object. It needs to be linked via an #IBOutlet.
Also, you should Ctrl + Drag from the collection view to the view controller object on the storyboard and select Data Source and Delegate so that the collection view is correctly linked.
Let me know if this helps or if I have misunderstood your situation.
For me, i had:
func setupCollectionView(){
self.refreshControl = UIRefreshControl()
self.refreshControl.attributedTitle = NSAttributedString(string: "Refreshing content...")
self.refreshControl.addTarget(self, action: #selector(self.reload), for: .valueChanged)
collectionView!.addSubview(refreshControl)
}
It still wasn't working (I believe i had constraints preventing it somehow), so i added:
collectionView.alwaysBounceVertical = true
then all was good. Just in case someone else is facing the same issue.
For a better understanding, the full implementation
#IBOutlet private weak var collectionView: UICollectionView!
let refreshControl = UIRefreshControl()
override func viewDidLoad() {
super.viewDidLoad()
setupCollectionView()
}
func setupCollectionView(){
collectionView.delegate = self
collectionView.dataSource = self
collectionView.alwaysBounceVertical = true
self.refreshControl = UIRefreshControl()
self.refreshControl.attributedTitle = NSAttributedString(string: "Refreshing content...")
self.refreshControl.addTarget(self, action: #selector(self.refresh), for: .valueChanged)
collectionView!.addSubview(refreshControl)
}
#objc func refresh(_ sender:AnyObject) {
//do refreshing stuff
}
private let refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action: #selector(youFunction), for: .valueChanged)
refreshControl.attributedTitle = NSAttributedString(string: "Fetching Data ...", attributes: nil)
DispatchQueue.main.async {
self.refreshControl.endRefreshing()
yourCollectionViewOrTableView.reloadData()
}