【问题标题】:UIView got rendered before data from API returned using SwiftyJSON and AlamofireUIView 在使用 SwiftyJSON 和 Alamofire 从 API 返回的数据之前被渲染
【发布时间】: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 中使用它,甚至在计算视图的高度等等。
  • 所有计算的事情都需要在这个方法结束时完成,如下所述

标签: alamofire swifty-json swift3.2


【解决方案1】:

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

您不能阻塞主线程。

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

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

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

您还必须决定该数据是加载一次还是每次显示视图时加载。通过将调用放在 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))")
    
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2015-06-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-28
      • 2018-02-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多