等待swift for循环网络请求执行完毕(原生不使用任何框架)

问题描述 投票:0回答:1

我有一个请求任务,其中有一个与另一个请求任务的循环。我想完成循环请求任务,然后继续完成另一个。

let dispatchGroup = DispatchGroup()

override func viewDidLoad() {
   super.viewDidLoad()
   tableView.reloadData()
   fetchData()

   dispatchGroup.notify(queue: .main) {
       self.tableView.reloadData()
   }
}

func fetchData() {
        var movies: String?
        dispatchGroup.enter()
        print("Enter fetchData")
        let task = session.dataTask(with: url) { data, response, error in
                if error != nil || data == nil {
                    print("Client error!")
                    return
                }
                guard let response = response as? HTTPURLResponse, (200...299).contains(response.statusCode) else {
                    print("Server error!")
                    return
                }
                guard let mime = response.mimeType, mime == "application/json" else {
                    print("Wrong MIME type!")
                    return
                }
                do {
                    
                    let json = try JSONSerialization.jsonObject(with: data!, options: []) as? [String : Any]
                    if let result = json?["results"] as? Array<Dictionary<String, Any>> {
                        for results in result {
                            self.char = StarWarsData.init(name: results["name"] as! String, height: results["height"] as! String, mass: results["mass"] as! String, gender: results["gender"] as! String, birthyear: results["birth_year"] as! String, film: results["films"] as! [String])
                            let name = self.char.name
                            let height = self.char.height
                            let mass = self.char.mass
                            let gender = self.char.gender
                            let birthyear = self.char.birthyear
                            let charFilms = self.char.film
                            for theFilms in charFilms {
                                self.fetchFilms(films: theFilms) { (filmNames) in
                                    movies = filmNames
                                    print(movies!)
                                }
                                
                            }
                            let item = StarWarsData(name: name, height: height, mass: mass, gender: gender, birthyear: birthyear, film: charFilms)
                            self.dataArray.append(item)
                            self.dataNames.append(name)
                            DispatchQueue.main.async {
                                self.tableView.reloadData()
                            }
                        }
                    }
                }catch {
                    print("JSON error: \(error.localizedDescription)")
                }
            print("Leaving fetchData")
            self.dispatchGroup.leave()
        }
        task.resume()
    }

func fetchFilms(films: String, taskCallBack: @escaping (String) -> ()) {
        let url = URL(string: films)!
        var filmsArr: [String] = []
        var item: String!
        var joinItem: String!
        dispatchGroup.enter()
        print("Enter fetchFilms")
        let task = self.session.dataTask(with: url, completionHandler: { (data, response, error) -> Void in
               
                if error != nil || data == nil {
                    print("Client error!")
                    return
                }
                guard let response = response as? HTTPURLResponse, (200...299).contains(response.statusCode) else {
                    print("Server error!")
                    return
                }
                guard let mime = response.mimeType, mime == "application/json" else {
                    print("Wrong MIME type!")
                    return
                }
                do {
                    let json = try JSONSerialization.jsonObject(with: data!, options: []) as? [String : Any]
                    if let results = json?["title"] as? String {
                        for results in results {
                            item = String(results)
                            filmsArr.append(item)
                        }
                        joinItem = filmsArr.joined(separator: "")
                        taskCallBack(joinItem)
                    }
                }catch {
                    print("JSON error: \(error.localizedDescription)")
                }
            print("Leaving fetchFilms")
            self.dispatchGroup.leave()
            })
             task.resume()
    }

所以检查一下打印语句,你就会明白我想要什么。 这是我的输出:

Enter fetchData
Enter fetchFilms
Enter fetchFilms
Enter fetchFilms
Enter fetchFilms
Enter fetchFilms
Enter fetchFilms
Enter fetchFilms
Enter fetchFilms
Enter fetchFilms
Enter fetchFilms
Leaving fetchData
A New Hope
Leaving fetchFilms
The Empire Strikes Back
Leaving fetchFilms
Return of the Jedi
Leaving fetchFilms
The Force Awakens
Leaving fetchFilms
Revenge of the Sith
Leaving fetchFilms
The Empire Strikes Back
Leaving fetchFilms
The Phantom Menace
Leaving fetchFilms
Attack of the Clones
Leaving fetchFilms
Revenge of the Sith
Leaving fetchFilms
The Phantom Menace
Leaving fetchFilms
Notify table reloaded

我就是想要这个:

Enter fetchData
Enter fetchFilms
Enter fetchFilms
Enter fetchFilms
Enter fetchFilms
Enter fetchFilms
Enter fetchFilms
Enter fetchFilms
Enter fetchFilms
Enter fetchFilms
Enter fetchFilms
A New Hope
Leaving fetchFilms
The Empire Strikes Back
Leaving fetchFilms
Return of the Jedi
Leaving fetchFilms
The Force Awakens
Leaving fetchFilms
Revenge of the Sith
Leaving fetchFilms
The Empire Strikes Back
Leaving fetchFilms
The Phantom Menace
Leaving fetchFilms
Attack of the Clones
Leaving fetchFilms
Revenge of the Sith
Leaving fetchFilms
The Phantom Menace
Leaving fetchFilms
Leaving fetchData
Notify table reloaded

我想以某种方式在打印语句

Leaving fetchData
之前暂停任务并完成
func fetchFilms
的整个过程,然后继续打印语句
Leaving fetchData
。实际上
func fetchData()
func fetchFilms
结束之前就完成了,我没有拍我想要的电影。顺便说一句,
print(movies!)
声明给了我电影,但为时已晚。

ios swift grand-central-dispatch
1个回答
0
投票

[编辑]:为了突出中篇文章的主要思想,还删除了信号量,这并不是真正的快速风格。

如果您希望一个函数在另一个函数调用之前完成(特别是在数据任务的情况下),您可以使用操作。

我找到了一篇更好的文章来指导您如何实现它。 https://medium.com/@oleary.audio/simultaneous-asynchronous-calls-in-swift-9c1f5fd3ea32

© www.soinside.com 2019 - 2024. All rights reserved.