首页 > 解决方案 > 不断检索到目的地 MapKIt 的时间

问题描述

我的目标是有两个用户,其中一个步行/骑自行车/开车走向另一个,让另一个用户检查另一个用户到达的剩余时间和距离。为了实现这一点,我目前正在使用 FIR 实时数据库。

我想我可以使用 MKDirections.Request 来计算剩余时间。但当然是我实现它的方式:

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

    directionsRequest.source = MKMapItem(placemark: MKPlacemark(coordinate: CLLocationCoordinate2D(latitude: coordinates.latitude, longitude: coordinates.longitude), addressDictionary: nil))
    directionsRequest.destination = MKMapItem(placemark: MKPlacemark(coordinate: CLLocationCoordinate2D(latitude: destination.latitude, longitude: destination.longitude), addressDictionary: nil))
                
                
    let directions = MKDirections(request: directionsRequest)
    var approxTime: Double = 9999
    
    directions.calculate { [self] (response, error) -> Void in
         guard let response = response else {
             if let error = error {
                 print("Error: \(error)")
             }
             return
         }

        if response.routes.count > 0 {
            let route = response.routes[0]
            approxTime = route.expectedTravelTime
            }
         }
     }
}

其中方向请求被定义为

let directionsRequest: MKDirections.Request = MKDirections.Request()

init() {
    directionsRequest.requestsAlternateRoutes = true
    directionsRequest.transportType = .automobile
}

正如您可能想象的那样,在最大化请求尝试一段时间后,此实现会失败,并返回以下错误

Error: Error Domain=MKErrorDomain Code=3 "Directions Not Available" UserInfo={NSLocalizedFailureReason=Route information is not available at this moment., MKErrorGEOError=-3, MKErrorGEOErrorUserInfo={ details = ( { intervalType = short; maxRequests = 50; " throttler.keyPath" = "app:someapp/0x20200/short(default/any)"; timeUntilReset = 31; windowSize = 60; } ); timeUntilReset = 31; }, MKDirectionsErrorCode=3, NSLocalizedDescription=方向不可用}

我可以将对该函数的调用限制为每 5 秒一次,但是看到苹果限制了请求,我认为我在这里的路径不正确。有没有更好的方法来实现这一点?也许还有一些我没能找到的其他对象/功能

SN:目前使用 SwiftUI 5.5

编辑:我添加这个小评论来澄清它,问题是

directions.calculate

不能多次调用,我认为每 30 秒有 50 个请求。但是其他用户在实时数据库上每秒左右更新一次位置,所以这意味着每 1 秒进行一次计算,这会最大化计算请求。

标签: swiftmapkit

解决方案


在我看来,最好的方法是使用内置实时更新功能的 Firestore 来解决。Google 提供了一个看起来像这样的示例代码段。https://firebase.google.com/docs/firestore/query-data/listen#swift

db.collection("cities").document("SF")
    .addSnapshotListener { documentSnapshot, error in
      guard let document = documentSnapshot else {
        print("Error fetching document: \(error!)")
        return
      }
      guard let data = document.data() else {
        print("Document data was empty.")
        return
      }
      print("Current data: \(data)")
    }

本质上,这里发生的事情是每次SF更新文档时,都会在该闭包中触发一个新快照。它特别酷的地方在于,您可以使用它来通知接收方数据库的更新。因此,您还希望将文档配置为具有一些字段latlong快照侦听器正在监视这些更新的一些字段。发生更新时,请计算您的距离。这样做,您只需要在数据库上创建新值时进行计算,您还可以限制应用程序向数据库创建新值的频率。您需要做的就是确保每个人都在查看具有您期望值的正确文档。

另一个提示是让两个用户都向同一个文档报告。如果你这样做,它会变得更加容易,因为 snapshotListener 将首先监听本地更改,允许你在写入文档的任何时候计算你的距离,然后当收到它时,另一方也可以得到他们的更新。你的可能看起来像这样。

db.collection("yourTripIdentifer").document("yourGroupIdentifier")
    .addSnapshotListener { documentSnapshot, error in
      guard let document = documentSnapshot,
            let data =  document.data() else { return }

      //We have data, let's use it.
      calculateDistance(from: data)
    }

推荐阅读