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

标签 ios swift api grand-central-dispatch

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

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!) 声明给了我电影,但为时已晚。

最佳答案

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

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

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

关于ios - 等待 swift for 循环网络请求执行完毕(原生不使用任何框架),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58365724/

相关文章:

ios - 脱机时 SDWebImageView 缓存问题和转义 URL 百分比

ios - 无法在 TableViewController 之间传递数据

windows - 在 Win7 登录屏幕上运行应用程序

ios - FMDB ResultSet 总是只返回一行

ios - 如何独立于标签栏项目标题更改uiviewcontroller标题

ios - GCD 终止请求

php - 如何使用 facebook php sdk v4 和 graph api 2.x 以管理员身份在 facebook 页面墙上发布帖子

iOS swift 使用 alamofire 在应用程序和共享扩展之间共享 cookie

enums - 为什么这需要一个 if 语句来执行

api - 如何跟踪用户在YouTube Player API中观看视频花了多少时间