Reputation: 454
In my TableViewController, I have an @objc function that fetches data using Alamofire. The function is called by the refreshController when the user pulls down to trigger a pull refresh.
The pull refresh is declared like so:
let refreshControl = UIRefreshControl()
tableView.refreshControl = refreshControl
self.refreshControl!.addTarget(self, action: #selector(refresh(sender:)), for: .valueChanged)
And the function it runs:
@objc func refresh(sender:AnyObject) {
let defaults = UserDefaults.standard
if let mode = defaults.string(forKey: defaultsKeys.mode) {
self.mode = mode
}
self.tableData.removeAll()
print(mode)
Alamofire.request(mode).response { response in
let xml = SWXMLHash.config {
config in
config.shouldProcessLazily = true
}.parse(response.data!)
for elem in xml["rss"]["channel"]["item"].all {
self.tableData.append(elem["title"].element!.text)
}
print("Completed Data Gather")
self.mainTable?.reloadData()
self.refreshControl!.endRefreshing()
}
}
The issue comes when I attempt to call the pull refresh function programmatically using
self.refreshControl!.beginRefreshing()
self.refreshControl!.sendActions(for: .valueChanged)
The function executes (as observed in the console due to the print statements) and the data is fetched, but the tableView refuses to refresh. I know the data is fetched properly because the next time the user manually pull refreshes the tableView updates with the new data.
TL;DR My tableView properly reloads when the user manually pull refreshes, but not when the pull refresh is called programmatically using.
Upvotes: 0
Views: 171
Reputation: 476
As Paul mentioned in the comments, this is because UI updates must be dispatched on the main thread.
Alamofire is asynchronous and runs on a background thread. With that being said, all of the code within your Alamofire request will execute on the background thread.
In order to execute code on the main thread, utilize the following:
DispatchQueue.main.async {
// Update UI ie. self.mainTable?.reloadData()
}
Upvotes: 1