Как я могу остановить метод ‘calculate’ класса ‘MKDirections’ от слишком большого количества запросов на вычисление расстояния?

#ios #swift #mapkit #mkdirection

#iOS #swift #mapkit #mkdirection

Вопрос:

Я делаю запросы на вычисление расстояния от моего текущего местоположения до мест расположения кемпинга в массиве countySites , используя calculate() метод MKDirections класса в for цикле. Когда у меня есть массив длиной 47 кемпингов, вычисляются только некоторые расстояния до кемпинга, остальные выдают сообщение об ошибке, предполагающее, что выполняется слишком много запросов. Я не знаю, как проверить, что calculate() он не слишком занят, прежде чем я сделаю запрос в for цикле.

Я попытался поместить 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()

            }
        }

    }
  

Комментарии:

1. Я получаю сообщение об ошибке из 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})

2. Когда я пытаюсь использовать while решение цикла, значение isCalculating всегда равно false, поэтому он никогда не выполняет код внутри while блока цикла. isCalculating только когда-либо true в else инструкции в замыкании, когда есть ненулевое значение для error

3. Возможно, вы ищете ограничитель скорости. Используйте это ключевое слово для поиска, и вы найдете решения.

4. @Gerd Castan Спасибо, я посмотрю это.

5. @Gerd Castan Я попробовал ограничитель скорости, но установка скорости на 1 токен каждую секунду по-прежнему не помогает слишком многим запросам

Ответ №1:

Единственное решение этой проблемы — просто сохранить массив MKRoute, и всякий раз, когда вы сталкиваетесь с новым путем, просто сохраните в этом массиве и используйте тот же массив для рисования пути, используя этот метод, вы также можете сохранять вызовы расстояния MapKit

Проверьте приведенный ниже фрагмент, который сработал для меня

 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%, и я надеюсь, что вы сможете использовать эту логику, чтобы избежать этой проблемы.

Комментарии:

1. как мы можем показать отслеживание в реальном времени, используя то же решение?

2. Да, вы можете это сделать, но сохраняйте таймер на каждые X секунд и вызывайте этот метод для обновления карты.