通过 Alamofire,想获取数据并将其插入 TableView,但在完成插入之前,TableView 已加载
Posted
技术标签:
【中文标题】通过 Alamofire,想获取数据并将其插入 TableView,但在完成插入之前,TableView 已加载【英文标题】:By Alamofire, would like to get data and insert it to TableView, but before completing of inserting, TableView is loaded 【发布时间】:2019-01-11 15:51:11 【问题描述】:正如我在标题中所写,我正在使用 Alamofire 获取数据,然后对其进行解码并将其附加到列表“articleList”中,然后尝试将其插入到 TableView,但似乎 TableView 加载在首先,然后收集数据并将其插入到列表中。 我想先进行插入,然后加载 TableView 但我找不到解决方案。我只是通过将 defer 放入 viewDidLoad 并制作 tableView.realodData 来尝试它,但它不起作用......有人可以给我任何关于这种情况的想法吗?
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))")
【问题讨论】:
【参考方案1】:不要在viewDidLoad
方法中写入tableView.reloadData()
,而是应该在完成将所有articles
追加到articleList
数组后写入。
示例代码:
viewDidLoad()
应该是这样的:
override func viewDidLoad()
super.viewDidLoad()
updateNewsData()
updateNewsData()
应该是这样的:
func updateNewsData()
getNewsData() (articles) in
guard let articleArray = articles?.articles else
fatalError("cannot get articles.")
articleList.append(contentsOf: articleArray)
DispatchQueue.main.async
tableView.reloadData()
【讨论】:
【参考方案2】:defer
中的代码在方法“返回”之后执行,或者例如在某个循环的当前循环返回之后执行
由于viewDidLoad
返回Void
,此方法在调用updateNewsData()
后立即返回,并且它不会等待从内部调用的另一个方法返回或在某个闭包内的代码执行后(defer
'在执行某些闭包后不执行,因为在闭包内部你不能为声明闭包的方法返回值)。
要修复您的代码,只需在附加文章后重新加载表格视图数据
for article in articleArray
self.articleList.append(article)
tableView.reloadData()
【讨论】:
【参考方案3】:Defer 块将在执行离开当前范围时执行,另一方面,您的请求是异步块,这意味着当调用 tableView.reloadData() 时,请求可能仍在处理中。
请求完成后需要调用reloadData:
override func viewDidLoad()
super.viewDidLoad()
updateNewsData()
...
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")
DispatchQueue.main.async
tableView.reloadData()
【讨论】:
以上是关于通过 Alamofire,想获取数据并将其插入 TableView,但在完成插入之前,TableView 已加载的主要内容,如果未能解决你的问题,请参考以下文章
swift 4 Alamofire 解析数据并在 UILabel 上显示?
如何使用 Alamofire 4.0 获取 JSON 字典/数组并将其显示在 tableView Cell 上
我需要接受 alamofire 关闭的响应并将其发送到另一个班级 [重复]