如何修复每个的geocodeAddressString闭包

时间:2019-05-02 19:16:18

标签: swift asynchronous

我在数据库中有任务模型(使用领域),它由id,标题,距离,经度,纬度,customerAddress组成。我正在尝试更新我的任务距离。我是新手,所以我不明白如何修复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 :(得分:0)

使用以下代码解决了此问题:

   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用于等待对所有地址进行地理编码。