Samip Shah Samip Shah - 1 month ago 13
iOS Question

UIRefresh control endRefreshing doesn't work

When refresh control is triggered by swiping the tableview down, if there is no internet connection, a alert is shown and the refresh control is expected to end refreshing but it doesn't end refreshing even added in main thread

class JobsForCategoryVC: UIViewController {
//MARK:-Outlets
@IBOutlet weak var jobTableView: UITableView!
@IBOutlet weak var activityIndicator: UIActivityIndicatorView!

//MARK:-Properties
var refreshControl:UIRefreshControl!
var jobCategory:JobCategoryDB!
var pageNumber:Int = 1
var downloadMore:Bool = true
var jobs = [JobModel]()


//MARK:-LifeCycle
override func viewDidLoad() {
super.viewDidLoad()
setupView()
freshDownload()
}

func setupView(){

refreshControl = UIRefreshControl()
refreshControl.attributedTitle = NSAttributedString(string: "Loading fresh Jobs")
refreshControl.addTarget(self, action: #selector(self.freshDownload), for: .valueChanged)
jobTableView.addSubview(refreshControl)

}

func freshDownload(){
pageNumber = 1
downloadMore = true
downloadJobsFrom(top: true)
}


func downloadJobsFrom(top:Bool){
if !refreshControl.isRefreshing && top{
activityIndicator.startAnimating()
}


let url = URLStringList.getSearchCategoryJobString(pageNumber: pageNumber, categoryId: jobCategory.id!)

if let url = URL(string: url){
Alamofire.request(url, method: .get).responseJSON { (response) in

if response.result.isSuccess{
let json = response.result.value

let model = Mapper<JobModel>().mapArray(JSONArray: json as! [[String : Any]])

if model?.count == 0{
self.downloadMore = false
}
if let jobs = model{
if top{
self.jobs = jobs
}else{
self.jobs += jobs
}

self.jobTableView.reloadData()
self.pageNumber += 1
}
self.refreshControl.endRefreshing()
self.activityIndicator.stopAnimating()

}else{

self.activityIndicator.stopAnimating()
DispatchQueue.main.async(execute: {
self.refreshControl.endRefreshing()
self.jobTableView.reloadData()
})

if top{
showInternetConnectionAlert(viewController: self, activityIndicator: self.activityIndicator, completion: nil)
}
}

}
}

}
}


extension JobsForCategoryVC:UITableViewDataSource{

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if jobs.count > 0 {
jobTableView.backgroundView = nil
let cellCount = jobs.count + ((jobs.count-1)/(AdForNumberOfCells-1)) + 1
return cellCount
}

jobTableView.backgroundView = Bundle.main.loadNibNamed("PullToRefreshView", owner: nil, options: nil)?.first as? PullToRefreshView
return 0
}


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row % AdForNumberOfCells == 0{
if let cell = tableView.dequeueReusableCell(withIdentifier: "JobsAdTableViewCell", for: indexPath) as? JobsAdTableViewCell{
cell.controller = self
return cell
}

}else{

if let cell = tableView.dequeueReusableCell(withIdentifier: "JobsTableViewCell", for: indexPath) as? JobsTableViewCell{
let index = NSIndexPath(item: indexPath.row-(indexPath.row/AdForNumberOfCells)-1, section: 0)
cell.configure(job: jobs[index.row])
return cell
}

}

return UITableViewCell()
}

}

extension JobsForCategoryVC:UITableViewDelegate{


func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let webView = storyboard?.instantiateViewController(withIdentifier: "WKWebVC") as? WKWebVC{
if indexPath.row % AdForNumberOfCells == 0 {
return
}
let index = NSIndexPath(item: indexPath.row-(indexPath.row/AdForNumberOfCells)-1, section: 0)

if let urlString = jobs[index.row].url{
webView.url = urlString
webView.titleString = jobs[index.row].title
present(webView, animated: true, completion: nil)
}

}
}

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if indexPath.row == self.jobs.count - 1 && downloadMore{
downloadJobsFrom(top: false)
}
}
}

Answer

Simple way of doing this is

DispatchQueue.main.async(execute: {
     self.jobTableView.reloadData()
     self.refreshControl.endRefreshing()
     self.activityIndicator.stopAnimating()
     self.refreshControl.setContentOffset(CGPoint.zero, animated: true)

})
Comments