Как исправить закрытие geocodeAddressString для каждого - PullRequest
0 голосов
/ 02 мая 2019

У меня есть модель задачи в базе данных (с использованием области), которая состоит из идентификатора, заголовка, расстояния, долготы, широты, customerAddress. Я пытаюсь обновить расстояние до задачи. Я новичок в Swift, поэтому я не понимаю, как мне исправить закрытие geoCoder.geocodeAddressString, чтобы все задачи обновлялись с расстояния. (когда у задачи нет широты и долготы, я проверяю, есть ли у нее привычный адрес, используя geocodeAddressString

    func updateTasksDistance() {
        // get tasks for db
        guard let tasks = Task.getAllUserTasks() else { return }

        // last tracked location
        guard let lastLocation = lastLocation else { return }

        let myLocation = CLLocation(latitude: lastLocation.coordinate.latitude, longitude: lastLocation.coordinate.longitude)

        var distance = 0

        tasks.forEach({ (task) in
            // check if task has longitude and latitude
            if let lat = Double(task.latitude), let long = Double(task.longitude), lat != 0 && long != 0 {
                let taskLocation = CLLocation(latitude: lat, longitude: long)
                distance = Int(taskLocation.distance(from: myLocation))
            } else if !task.customerAddress.isEmpty { // check if task has address
                geoCoder.geocodeAddressString(task.customerAddress) { placemarks, _ in
                    if let placemark = placemarks?.first, let location = placemark.location  {
                        self.taskLocationCoordinate = CLLocation(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude )
                    }
                }
            }

            // check if we have closure location??
            if let taskLocation = taskLocationCoordinate {
                distance = Int(CLLocation(latitude: taskLocation.coordinate.latitude, longitude: taskLocation.coordinate.longitude).distance(from: myLocation))

                taskLocationCoordinate = nil
            }

            // update my distance to task
            updateTaskDistanceDb(task: task, with: distance)

            // reset distance
            distance = 0
        })
    }

// update task distance in db
    fileprivate func updateTaskDistanceDb(task: Task, with distance: Int) {
        let realm = try? Realm()

        if let realm = realm {
            do {
                try realm.write {
                    task.distance = distance
                }
            } catch {
                print("error")
            }
        }
    }

Текущий результат: расстояние корректно обновляется там, где не вызывается замыкание, но когда вызывается замыкание, я получаю результаты не в порядке

ожидаемый результат: все заданные расстояния относительно моего корректно обновлены

1 Ответ

0 голосов
/ 03 мая 2019

Исправлена ​​эта проблема с использованием этого кода:

   fileprivate func geoCode(addresses: [String], results: [CLPlacemark] = [], completion: @escaping ([CLPlacemark]) -> Void ) {
        guard let address = addresses.first else {
            completion(results)
            return
        }

        let geoCoder = CLGeocoder()
        geoCoder.geocodeAddressString(address) { placemarks, _ in
            var updatedResults = results

            if let placemark = placemarks?.first {
                updatedResults.append(placemark)
            }

            let remainingAddresses = Array(addresses[1..<addresses.count])
            self.geoCode(addresses: remainingAddresses, results: updatedResults, completion: completion)
        }
    }

    func updateTasksDistance() {
        // get tasks for db
        guard let tasks = Task.getAllUserTasks() else { return }

        // last tracked location
        guard let lastLocation = lastLocation else { return }

        let myLocation = CLLocation(latitude: lastLocation.coordinate.latitude, longitude: lastLocation.coordinate.longitude)

        let dispatchGroup = DispatchGroup()
        for task in tasks where !task.customerAddress.isEmpty {

            let addresses = [task.customerAddress]

            dispatchGroup.enter()
            geoCode(addresses: addresses) { results in
                guard let customerAdress = results.first else { return }
                guard let customerLocatin = customerAdress.location else { return }

                let taskLocation = CLLocation(latitude: customerLocatin.coordinate.latitude,
                                              longitude: customerLocatin.coordinate.longitude )
                // do additional sutff
                dispatchGroup.leave()
            }
        }

        dispatchGroup.notify(queue: DispatchQueue.main, execute: {
               // got all the address
            }
        })
    }

Рекурсивная функция геокодирования помогла вычислить все координаты, а dispatchGroup.notify для ожидания, пока все адреса не будут геокодированы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...