通过 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 上显示?

如何从数据库中获取最后插入的 id 并将其发送到组件?

如何使用 Alamofire 4.0 获取 JSON 字典/数组并将其显示在 tableView Cell 上

我需要接受 alamofire 关闭的响应并将其发送到另一个班级 [重复]

如何使用 laravel 集合获取最后插入的 ID 并将其插入到第二个表中?

如何获取最后插入的自动递增 id 并将其插入 laravel 中的另一个表中?