避免Swift同时调用viewDidLoad中的方法得到"Index out of range"

Avoid Swift Calling methods in viewDidLoad at the same time and getting "Index out of range"

你能帮我一下吗?我想知道如何在另一个函数结束后调用 swift 函数,我认为它是同时调用两个函数。这是我的 viewDidLoad:

    override func viewDidLoad() { 
      super.viewDidLoad() 

        downloadJsonEscuelas(id_responsable: "5")
        downloadJsonAnuncios(id_escuela:("\arrayEscuelas[0].id_escuela!)"))    
}

第一个函数"downloadJsonEscuelas"用数据填充数组"arrayEscuelas",第二个函数接收数据作为参数:

下载JsonEscuelas:

func downloadJsonEscuelas(id_responsable: String) {  

        guard let downloadURL = URL(string: Constantes.URLbase+"json/getescuelas.php?id="+id_responsable) else { return }
        URLSession.shared.dataTask(with: downloadURL) { data, urlResponse,
            error in
            guard let data = data, error == nil, urlResponse != nil else {
                print("Something went wrong")
                return
            }
            print("Escuelas downloaded")

            do
            {

                let downloadedEscuelas = try JSONDecoder().decode([Escuelas].self, from: data)
                self.arrayEscuelas = downloadedEscuelas


                DispatchQueue.main.async {


                    print("id escuela actual:"+self.idEscuelaActual!+":)")
                    self.escuelaTextBox.text = self.arrayEscuelas[0].escuela!
                    self.idEscuelaActual = "\(self.arrayEscuelas[0].id_escuela!)" as String

                }
            } catch let jsonErr {
                print("Error: ", jsonErr)
            }
            }.resume() 
    }

下载JsonAnuncios:

func downloadJsonAnuncios(id_escuela: String) {

        guard let downloadURL = URL(string: Constantes.URLbase+"json/getanuncios.php?id="+id_escuela) else { return }
        URLSession.shared.dataTask(with: downloadURL) { data, urlResponse,
            error in
            guard let data = data, error == nil, urlResponse != nil else {
                print("Something went wrong")
                return
            }
            print("downloaded")

            do
            {

                let downloadedAnuncios = try JSONDecoder().decode([Anuncios].self, from: data)
                self.arrayAnuncios = downloadedAnuncios

                print(self.arrayAnuncios[0].titulo!)   

                DispatchQueue.main.async {
                    self.tableView.reloadData()

                }
            } catch let jsonErr {
                print("Error: ", jsonErr)
            }
            }.resume()
    }

我认为它同时调用了两个函数,所以它没有在第一个函数中填充数组。当我将参数作为普通数字传递时,一切顺利,例如:

downloadJsonAnuncios(id_escuela: "2")  

希望你能帮到我,非常感谢。

在第一个调用 (downloadJsonEscuelas(id_responsable: "5")) 的完成中插入第二个调用 (this downloadJsonAnuncios(id_escuela:("\arrayEscuelas[0].id_escuela!)")))

func downloadJsonEscuelas(id_responsable: String) {  

        guard let downloadURL = URL(string: Constantes.URLbase+"json/getescuelas.php?id="+id_responsable) else { return }
        URLSession.shared.dataTask(with: downloadURL) { data, urlResponse,
            error in
            guard let data = data, error == nil, urlResponse != nil else {
                print("Something went wrong")
                return
            }
            print("Escuelas downloaded")

            do
            {

                let downloadedEscuelas = try JSONDecoder().decode([Escuelas].self, from: data)
                self.arrayEscuelas = downloadedEscuelas


                DispatchQueue.main.async {


                    print("id escuela actual:"+self.idEscuelaActual!+":)")
                    self.escuelaTextBox.text = self.arrayEscuelas[0].escuela!
                    self.idEscuelaActual = "\(self.arrayEscuelas[0].id_escuela!)" as String 



                }

                 // here  
                 downloadJsonAnuncios(id_escuela:("\arrayEscuelas[0].id_escuela!)"))

            } catch let jsonErr {
                print("Error: ", jsonErr)
            }
            }.resume() 
    }

为什么不在第一个的闭包中调用第二个

do {
    let downloadedEscuelas = try JSONDecoder().decode([Escuelas].self, from: data)
    self.arrayEscuelas = downloadedEscuelas

    DispatchQueue.main.async {
        print("id escuela actual:"+self.idEscuelaActual!+":)")
        self.escuelaTextBox.text = self.arrayEscuelas[0].escuela!
        self.idEscuelaActual = "\(self.arrayEscuelas[0].id_escuela!)" as String
    }
    downloadJsonAnuncios(id_escuela:("\arrayEscuelas[0].id_escuela!)")) 
} catch let jsonErr {
     print("Error: ", jsonErr)
}
}.resume()

默认情况下,viewDidLoad 中的代码在 UIThread 上同步运行。 您的 API 调用在单独的线程上 运行 并且允许您的其他方法在完成之前执行。 您可能应该在您的方法中使用完成处理程序,这样您的第二个方法只会在您的 api 调用完成后被调用。

查看此答案以实施 CompletionHandler