Дождитесь окончания выполнения swift для циклических сетевых запросов (Native без использования какой-либо инфраструктуры) - PullRequest
0 голосов
/ 13 октября 2019

Итак, у меня есть задача запроса, и внутри нее у меня есть цикл с другой задачей запроса. Я хочу выполнить задачу запроса цикла, а затем продолжить выполнение другой.

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!) дает мне фильмы, но уже слишком поздно.

1 Ответ

0 голосов
/ 13 октября 2019

[Редактировать]: чтобы выделить основную идею среднего поста, также удалены семафоры, не очень быстрый стиль.

Вы можете использовать операцию, если хотите, чтобы функция была завершена до вызова другой функции (особеннов случае задач с данными).

Я нашел лучший пост, в котором вы найдете инструкции по его реализации. https://medium.com/@oleary.audio/simultaneous-asynchronous-calls-in-swift-9c1f5fd3ea32

...