Почему мой для l oop не завершается, когда я помещаю его в viewDidLoad? - PullRequest
1 голос
/ 29 января 2020

почему тело моей функции выполняется только один раз, хотя я помещаю тело внутрь для l oop, которое должно быть выполнено 7 раз?

мои строки кода выглядят следующим образом

 override func viewDidLoad() {
            super.viewDidLoad()
            getLocationFromGeoCoding()
        }
    func getLocationFromGeoCoding() {
        for index in 0...6{
         geoCoder.reverseGeocodeLocation(sevenWorldWonderOb[index].location ?? CLLocation()) {[weak self] (placemarks, err) in
        if let err = err {
            print("Error",err.localizedDescription)
            return
        }else {
            guard let placemark = placemarks?.first else {return}
             let streetNumber = placemark.subThoroughfare
             let street = placemark.thoroughfare
             let city = placemark.locality
             let state = placemark.administrativeArea
            let country = placemark.country
            let Address = "\(streetNumber == nil ? "" : streetNumber!) \(street == nil ? "" : street!) \(city == nil ? "" : city!) \(state == nil ? "" : state!) \(country == nil ? "" : country!)"
            self?.addressLocation.append(Address)
            self?.wonderAddress.text = self?.addressLocation[index]
            }
        }

    }
}

Ответы [ 3 ]

4 голосов
/ 29 января 2020

Вы можете использовать DispatchGroup, когда работаете в asyn c. reverseGeocodeLocation работает асинхронно. если вы хотите знать, когда у вас есть все адреса в вашем массиве

func getLocationFromGeoCoding() {
let group = DispatchGroup()
        for index in 0...6{
         group.enter()
         geoCoder.reverseGeocodeLocation(sevenWorldWonderOb[index].location ?? CLLocation()) {[weak self] (placemarks, err) in
            defer {
               group.leave()
           }
        if let err = err {
            print("Error",err.localizedDescription)

        } else {
            guard let placemark = placemarks?.first else { return}
             let streetNumber = placemark.subThoroughfare
             let street = placemark.thoroughfare
             let city = placemark.locality
             let state = placemark.administrativeArea
            let country = placemark.country
            let Address = "\(streetNumber == nil ? "" : streetNumber!) \(street == nil ? "" : street!) \(city == nil ? "" : city!) \(state == nil ? "" : state!) \(country == nil ? "" : country!)"
            self?.addressLocation.append(Address)
            self?.wonderAddress.text = self?.addressLocation[index]
            }


group.notify(queue: .main, execute: { // executed after all async calls in for loop finish
    print(“Got all addresses”)
    // do whatever you want to do on getting all addresse
})

    }

игровая площадка протестирована

enter image description here

1 голос
/ 29 января 2020

Я думаю, что есть недоразумение о том, как работает reverseGeocodeLocation. Как правило, я ожидаю, что он работает асинхронно.

geoCoder.reverseGeocodeLocation(sevenWorldWonderOb[index].location ?? CLLocation())
{
    [weak self] (placemarks, err) in
    print ("here in closure")
    // ...
}

Это означает, что он напечатает здесь в замыкании и выполнит все остальные операции внутри замыкания асинхронно , когда он - когда-нибудь в будущем - получит информацию о местоположении из некоторого фонового рабочего потока.

Но все это зависит от того, как geoCoder реализует reverseGeocodeLocation. Я ожидал бы, что замыкание действительно вызывается семь раз, но вам нужно подождать некоторое время (пожалуйста, проверьте операторы печати).

Возможно, вам также нужно обновить точки выхода в главном потоке (используя DispatchQueue.main.async), но это также зависит от того, как вызывается замыкание.

0 голосов
/ 29 января 2020

ReverseGeocodeLocation - это тип асинхронного типа, который обрабатывает свой метод с помощью обработчика завершения. Итак, когда вы вызываете этот метод для L oop. Ваш for l oop работает нормально, но из-за выходящего обработчика завершения обратного геокодирования он не будет обрабатывать код после этой строки

geoCoder.reverseGeocodeLocation(sevenWorldWonderOb[index].location ?? CLLocation()) {[weak self] (placemarks, err) in

Итак, вы получаете последнее значение индекса для l oop всегда. Из-за экранирующего обработчика завершения он выбрасывает вызов из метода reverseGeocodingLocation, а затем возвращается к функциональности, написанной в этом методе, и обрабатывает это, но в вашем случае, когда он выбрасывает вызов из метода, тогда l oop всегда интегрируется одним и обрабатывает до конца индекса, после чего он будет обрабатывать функциональность в соответствии с этим методом. Чтобы решить эту проблему, вам нужно управлять обработчиком завершения обработчика reverseGeocodeLocation.

Проверить этот запрос стека тоже.

...