0

我想使用 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()
 }
4

2 回答 2

0

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))")

        }
    }
}
于 2017-11-24T04:18:03.770 回答
0

了解应用程序运行多个线程很重要。主线程,也称为 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
}
于 2017-11-24T04:34:13.513 回答