【问题标题】:How can I stop the 'calculate' method of the 'MKDirections' class from making too many requests for distance calculation?如何阻止“MKDirections”类的“计算”方法发出过多的距离计算请求?
【发布时间】:2019-04-22 14:11:16
【问题描述】:

我在for 循环中使用MKDirections 类的calculate() 方法请求计算从我当前位置到数组countySites 中的露营地位置的距离。当我有一个长度为 47 个露营地的数组时,只计算了一些露营地距离,其余的会产生一条错误消息,提示正在发出太多请求。在for 循环中发出请求之前,我不知道如何检查calculate() 是否太忙。

我尝试在代码中放置一个while 循环,以反复检查仍在使用isCalculating Bool 属性处理的计算,但它无法停止错误消息。

            countySites = england.counties[selectedCounty!]!

            let sourcePlacemark = MKPlacemark(coordinate: currentCoordinate!)
            let request = MKDirections.Request()

            request.source = MKMapItem(placemark: sourcePlacemark)
            request.transportType = .automobile
            request.requestsAlternateRoutes = false
            let group = DispatchGroup()

            activityIndicator.startAnimating()

            // Step through sites one by one
            for siteIndex in 0..<countySites.count {

                var selectedSite = countySites[siteIndex]
                let destinationPlacemark = MKPlacemark(coordinate: selectedSite.locationCoordinate)

                request.destination = MKMapItem(placemark: destinationPlacemark)

                let distanceAndDirections = MKDirections(request: request)

                if currentCoordinate != nil {

                    group.enter()
                    distanceAndDirections.calculate { (response, error) in
                        if error == nil {

                            let distanceInMetres = response?.routes.first?.distance
                            let distanceInMiles = distanceInMetres! / 1610
                            let roundedDistanceInMiles = Int(distanceInMiles.rounded())
                            let distanceToSite = roundedDistanceInMiles

                            selectedSite.distance = distanceToSite
                            self.countySites[siteIndex] = selectedSite

                        } else {
                            print(error.debugDescription)                            
                        }
                        group.leave()
                    }

                }

            }

            group.notify(queue: .main) {

                self.countySites = self.sortByDistance(sites: self.countySites)

                self.tableView.reloadData()

                self.activityIndicator.stopAnimating()

            }
        }

    }

【问题讨论】:

  • 我从print(error.debugDescription)语句Optional(Error Domain=MKErrorDomain Code=3 "Directions Not Available" UserInfo={NSLocalizedFailureReason=Route information is not available at this moment., MKErrorGEOError=-3, MKErrorGEOErrorUserInfo={ }, MKDirectionsErrorCode=3, NSLocalizedDescription=Directions Not Available})得到错误信息
  • 当我尝试 while 循环解决方案时,isCalculating 的值始终为 false,因此它永远不会执行 while 循环块内的代码。当error 有非零值时,isCalculating 只会在闭包中的 else 语句中出现 true
  • 您可能正在搜索的是速率限制器。使用此关键字搜索您会找到的解决方案。
  • @Gerd Castan 谢谢,我会查一下。
  • @Gerd Castan 我尝试了速率限制器,但将速率设置为每秒 1 个令牌仍然无助于太多请求

标签: ios swift mapkit mkdirection


【解决方案1】:

解决这个问题的唯一方法是保留一个 MKRoute 数组,每当遇到新路径时,只需保存到该数组并使用相同的数组绘制路径,使用此方法可以节省 mapKit 距离电话也是如此

检查以下对我有用的 sn-p

var distanceArray: [MKRoute]? // like this create an array inside the class

func drawPath(destination: CLLocationCoordinate2D, source: CLLocationCoordinate2D) {

   let sourcePlacemark = MKPlacemark(coordinate: source, addressDictionary: nil)
   let destinationPlacemark = MKPlacemark(coordinate: destination, addressDictionary: nil)
    
   let sourceMapItem = MKMapItem(placemark: sourcePlacemark)
   let destinationMapItem = MKMapItem(placemark: destinationPlacemark)
    
    
   let directionRequest = MKDirectionsRequest()
   directionRequest.source = sourceMapItem
   directionRequest.destination = destinationMapItem
   directionRequest.transportType = .walking

   let directions = MKDirections(request: directionRequest)
    if distanceArray.count > 0 {
       guard let route = distanceArray.first?.routes else {return}
         self.showPath(route: route)
    } else {
       directions.calculate { (response, error) -> Void in
           guard let response = response else {
              if let error = error {
                 print("Error YuluMapView: \(error)")
              }
              return
            }
           guard let route = response.routes.first else {return}
           distanceArray.append(route)
          self.showPath(route: route)
        }
    }

}

func showPath(route: MKRoute) {
    self.add((route.polyline), level: MKOverlayLevel.aboveRoads)
    
    let rect = route.polyline.boundingMapRect
    self.setVisibleMapRect(rect, edgePadding: defaultEdgeInsets, animated: true)
}

它 100% 对我有用,希望您可以使用这个逻辑来避免这个问题。

【讨论】:

  • 我们如何使用相同的解决方案显示实时跟踪?
猜你喜欢
  • 2022-08-06
  • 2022-06-14
  • 2013-12-07
  • 2011-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多