As I'm writing at the title, I'm using Alamofire to get data and then decode it and append it to the list "articleList" and then try to insert it to TableView, but it seems that TableView is loaded at first, and then the data is collected and inserted to the list. I would like to make the insertion first, then loading TableView but I cannot find a solution. I just tried it by putting defer into viewDidLoad and make tableView.realodData, but it doesn't work... Could anybody give me any idea for this situation?
import UIKit
import Alamofire
class NewsViewController: UITableViewController {
var urlForApi = "https://newsapi.org/v2/top-headlines?country=jp&category=technology&apiKey=..."
var articleList = [Article]()
override func viewDidLoad() {
super.viewDidLoad()
updateNewsData()
defer {
tableView.reloadData()
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print(articleList.count)
return articleList.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = articleList[indexPath.row].title
return cell
}
// override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//
// }
func updateNewsData() {
getNewsData() { (articles) in
guard let articleArray = articles?.articles else
{fatalError("cannot get articles.")}
for article in articleArray {
self.articleList.append(article)
}
print("insert is done")
}
}
func getNewsData(completion: @escaping (ArticlesListResult?) -> Void) {
Alamofire.request(urlForApi, method: .get)
.responseJSON { response in
if response.result.isSuccess {
if let data = response.data {
let articles = try? JSONDecoder().decode(ArticlesListResult.self, from: data)
completion(articles)
}
} else {
print("Error: \(String(describing: response.result.error))")
}
}
}
}
Code inside defer
is executed after "return" of method or for example after return of current cycle of some loop
Since viewDidLoad
returns Void
, this method returns immediately after updateNewsData()
is called and it doesn't wait then another method which was called from inside returns or after code inside some closure is executed (defer
isn't executed after some closure is executed since inside closure you can't return value for method where closure was declared).
To fix your code, just reload table view data after you append articles
for article in articleArray {
self.articleList.append(article)
}
tableView.reloadData()