swift - 如何修复每个中的 geocodeAddressString 闭包

标签 swift asynchronous

我在数据库中有任务模型(使用领域),其中包含 id、标题、距离、经度、纬度、customerAddress。我正在尝试更新我的任务距离。我是 swift 新手,所以我不明白应该如何修复 geoCoder.geocodeAddressString 闭包,以便所有任务都会随距离更新。 (当任务没有纬度和经度时,我使用 geocodeAddressString 检查任务是否有 customeradress

    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")
            }
        }
    }

当前结果:在未调用闭包的情况下,距离会正确更新,但是当调用闭包时,我会得到乱序结果

预期结果:所有任务相对于我的距离都已正确更新

最佳答案

使用以下代码修复了此问题:

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

关于swift - 如何修复每个中的 geocodeAddressString 闭包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55958862/

相关文章:

ios - 如何淡出 iOS 12 上的 titleView 标签

ios - 通过后台获取的电池状态和电量?

swift - map View 上的倒圆圈叠加(MapKit、MKOverlay、Swift)

javascript - 类型错误 : task is not a function in async js parrallel

c# - 在 .NET 中使用 ConfigureAwait

ios - 对成员 'first(where)' 的模糊引用

json - 如何在 swift 5 中使用 Alamofire 5 在 api 中传递带有其他参数的个人资料图像

JAVA API Servlet异步调用

java - 如何处理多个 ListenableFuture? ( Spring )

.net - F# STA 线程异步