Reputation: 37
I've got a closure calculating distance and time between two points, but I need to extract the array of values (directions and journeyTimes) outside of the closure.
I'm pretty sure a completion handler is the way to go, but not too sure how to implement it.
My code:
var completionHandlers: [() -> Void] = []
@IBAction func calculateItinerary(_ sender: Any) {
// start calc
for index in 0...coordsOfCollective.count - 2 {
let sourceLocation = MKPlacemark(coordinate: coordsOfCollective[index])
let destinationLocation = MKPlacemark(coordinate: coordsOfCollective[index + 1])
let sourceMapItem = MKMapItem(placemark: sourceLocation)
let destinationMapItem = MKMapItem(placemark: destinationLocation)
let request = MKDirectionsRequest()
request.source = sourceMapItem
request.destination = destinationMapItem
request.transportType = .automobile
request.requestsAlternateRoutes = false
let directions = MKDirections(request: request)
directions.calculate { response, error in
if let route = response?.routes.first {
print("Distance: \(route.distance/1000) km, ETA: \(route.expectedTravelTime/60) mins")
self.distances.append(route.distance/1000)
self.journeyTimes.append(route.expectedTravelTime/60)
print(self.distances)
print(self.journeyTimes)
completionHandlers.append(?????)
} else {
print("Error!")
}
}
}
print(completionHandlers)
}
The directions.calculate has a declaration of calculate(completionHandler: @escaping MKDirectionsHandler), so I can see it is an escaping closure. But I don't know how I extract distances and journeyTimes arrays outside of it. The print functions currently produce values, but can't be accessed from elsewhere.
Any help is appreciated. Thanks.
Upvotes: 0
Views: 612
Reputation: 6579
var completionHandlers: [() -> Void] = []
for i in 1...10 {
let handler = {
print(i)
}
completionHandlers.append(handler)
}
After that you can execute the handlers:
completionHandlers[0]()
or, to make the code more expressive:
let handler = completionHandlers[0]
handler()
And to go through all of the handlers:
completionHandlers.forEach { handler in
handler()
}
Be careful, when you are storing the handler in an array, you have a strong reference to it. Because the closure keeps a strong reference to everything you are referring to within the closure, it's easy to create a reference cycle when you refer to self
:
let handler = {
self.myFunction()
}
You can avoid the retaicnycle by making a weak reference to self:
let handler = { [weak self] in
self?.myFunction()
}
Upvotes: 1