UIView 在使用 SwiftyJSON 和 Alamofire 从 API 返回的数据之前被渲染

Posted

技术标签:

【中文标题】UIView 在使用 SwiftyJSON 和 Alamofire 从 API 返回的数据之前被渲染【英文标题】:UIView got rendered before data from API returned using SwiftyJSON and Alamofire 【发布时间】:2017-11-24 03:24:34 【问题描述】:

我想使用 API 请求获取数据。数据是使用 SwiftyJson 和 Alamofire 获取的。问题是数据被获取,但视图在获取值之前被加载。我该如何解决这个问题?我的代码如下:

func fetchData()
    Alamofire.request(favUrl, method: .get, parameters: [:]).responseJSON 
        response in
        if response.result.isSuccess

            let dataFetched : JSON = JSON(response.result.value!)
            //print(dataFetched)
            let titleDisp = dataFetched["title"].arrayObject as? [String]
            //print(titleDisp)
            self.trackList = dataFetched["track_id"].arrayObject as? [String]

            print(self.trackList)

        else
            print("Error \(String(describing: response.result.error))")

        
    



override func viewDidLoad() 
    super.viewDidLoad()
    fetchData()
 

【问题讨论】:

你是说视图在数据加载之前就出现了?如果这是您要问的,从您的描述中不完全清楚吗?你提到你将在你的应用程序的各个部分使用这些数据。这是问题的一部分吗?编辑您的问题并加强对问题的描述。 视图在加载数据之前出现。我希望先加载获取的数据。 你打算在什么样的地方展示这些数据。如tableview、imageview 获取的数据是一个数组。我将在 textViews 中使用它,甚至在计算视图的高度等等。 所有计算的事情都需要在这个方法结束时完成,如下所述 【参考方案1】:

了解应用程序运行多个线程很重要。主线程,也称为 UI 线程,执行应用程序可见部分的操作,包括显示视图、对按钮做出反应等。

您不能阻塞主线程。

当您调用外部资源(如 API 调用或加载外部图像)时,这些资源会在单独的线程上执行。该线程独立于主线程。两个线程都不等待另一个。加载数据时,应用程序仍会对按钮做出反应。您要求的是在加载数据之前阻止显示视图。您可以这样做,但您必须了解这可能需要一些时间,具体取决于您的网络连接。您可以采用两种方法。

    转换到显示数据的视图,但在屏幕上放置一个“正在加载”元素,直到数据加载,然后移除“正在加载”元素,然后重新显示包含数据的视图。

    在显示视图之前加载数据。让前一个视图加载数据,然后转到必须显示数据的视图。

您还必须决定该数据是加载一次还是每次显示视图时加载。通过将调用放在 viewDidLoad 中,API 调用只会发生一次,直到应用程序重新启动。如果您希望每次显示屏幕时都加载数据,请将调用放在 viewWillAppear 中。

// Approach #1
func fetchData()

    self.showSpinner() 

    Alamofire.request(favUrl, method: .get, parameters: [:]).responseJSON 
        response in
        self.hideSpinner() 
        if response.result.isSuccess 

            let dataFetched : JSON = JSON(response.result.value!)
            //print(dataFetched)
            let titleDisp = dataFetched["title"].arrayObject as? [String]
            //print(titleDisp)
            self.trackList = dataFetched["track_id"].arrayObject as? [String]

            print(self.trackList)

            // Actually update the relevant screen elements here.

         else 
            print("Error \(String(describing: response.result.error))")
        
    


override func viewDidLoad() 
    super.viewDidLoad()
    //fetchData()


override func viewWillAppear() 
    super.viewWillAppear()
    fetchData()


func showSpinner() 
    // IMPLEMENT ME

func hideSpinner() 
    // IMPLEMENT ME

【讨论】:

【参考方案2】:

Alamofire 方法异步运行。不在 UIThread 中。然后您必须在方法运行完成后重新加载这些视图。

作为示例 - 表格视图

func fetchData()
    Alamofire.request(favUrl, method: .get, parameters: [:]).responseJSON 
        response in
        if response.result.isSuccess

            let dataFetched : JSON = JSON(response.result.value!)
            //print(dataFetched)
            let titleDisp = dataFetched["title"].arrayObject as? [String]
            //print(titleDisp)
            self.trackList = dataFetched["track_id"].arrayObject as? [String]

            print(self.trackList)

            // In here you have to reload, set your uiviews or all calculation

            tableview.reloadData()

        else
            print("Error \(String(describing: response.result.error))")

        
    

【讨论】:

以上是关于UIView 在使用 SwiftyJSON 和 Alamofire 从 API 返回的数据之前被渲染的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 Alamofire 和 SwiftyJSON 在 tableviewcell 中加载 JSON 数据

在 Haneke 和 SwiftyJSON 之间转换 JSON

iOS:使用 HanekeSwift 和 SwiftyJSON

在 swift 4.0 中使用 Alamofire/SwiftyJSON 时出错

使用 SwiftyJSON 解析 JSON 响应

如何在swift中使用alamofire和swiftyjson解析分页url?