I am trying to show a table view which shows institutions by car travel times.
- The query loops through a list of schools in the database to retrieve their coordinates
- Calculate the distance from the user's current location
- If the distance is less than 20 miles, calculate the eta time using MKDirections()
- Once the eta times have been calculated, append the relevant information to the table view's array, sort the array by eta times and only keep the top 10
The issue here is, there are often many institutions within 20 miles of the user's current location and MKDirections() limits the amount of requests you can make to calculate eta times in a given timeframe. So, quite often my table view is unable to show the eta times.
The obvious solution for me is to sort and trim the array before I calculate the eta times (thus avoiding the too many calculate eta requests issue).
What I tried:
- Append the data inside the for loop to 'Array1'
- Sort and trim Array1
- Outside/after the for loop, I loop through Array1 to calculate eta times and then append this data to Array2 which will be the array that feeds the tableview
I found that this doesn't work because the code outside/after the for loop is executed before the for loop is finished.
let schoolDB = Database.database().reference().child("Schools")
schoolDB.observe(.value, with: { (snapshot) in
self.subjectTimesArray.removeAll()
for child in snapshot.children {
let schoolSnapshot = child as! DataSnapshot
let approvalString = schoolSnapshot.childSnapshot(forPath: "Approved").value as! String
if approvalString == "Yes" {
let schoolID = schoolSnapshot.key
let schoolName = schoolSnapshot.childSnapshot(forPath: "Name").value as! String
let schoolLatitude = schoolSnapshot.childSnapshot(forPath: "Latitude").value as! Double
let schoolLongitude = schoolSnapshot.childSnapshot(forPath: "Longitude").value as! Double
let schoolLocation = CLLocation(latitude: schoolLatitude, longitude: schoolLongitude)
let distance = schoolLocation.distance(from: self.userLocation) / 1600
if distance < 20 {
let subjectDB = Database.database().reference().child("Subject/" + schoolID + "/" + date)
subjectDB.observeSingleEvent(of: .value, with: { (subjectSnapshot) in
let startTime = subjectSnapshot.childSnapshot(forPath: "Maths/Start").value as! String
let userPlacemark = MKMapItem(placemark: MKPlacemark(coordinate: userLocation.coordinate))
let schoolPlacemark = MKMapItem(placemark: MKPlacemark(coordinate: schoolLocation.coordinate))
let directionsRequest = MKDirections.Request()
directionsRequest.source = userPlacemark
directionsRequest.destination = schoolPlacemark
directionsRequest.requestsAlternateRoutes = false
directionsRequest.transportType = .automobile
let directions = MKDirections(request: directionsRequest)
directions.calculateETA(completionHandler: { (response, error) in
if let seconds = response?.expectedTravelTime {
let minutes = seconds / 60
self.subjectTimesArray.append(.init(schoolID: schoolID, schoolName: schoolName, distance: distance, eta: Int(minutes), subjectStart: startTime))
}
self.subjectTimesArray.sort(by: {$0.eta < $1.eta})
if self.subjectTimesArray.count > 10 {
self.subjectTimesArray.removeLast(self.subjectTimesArray.count - 10)
}
self.subjectTimesTableView.reloadData()
})
})
}
}
}
})