I have written something like this to calculate the driving distance between 2 points / locations.

Method Implementation:

Class 1:

static func calculateDistance(_ location1 : CLLocationCoordinate2D, location2: CLLocationCoordinate2D, completion: @escaping (_ distance: CLLocationDistance?) -> ()) {

    let start = MKMapItem(placemark: MKPlacemark(coordinate: location1))
    let destination = MKMapItem(placemark: MKPlacemark(coordinate: location2))
    let request = MKDirectionsRequest()
    request.source = start
    request.destination = destination
    request.requestsAlternateRoutes = false
    let direction = MKDirections(request: request)
    var distanceInMiles: CLLocationDistance?

    direction.calculate { (response, error) in
        if let response = response, let route = response.routes.first {
            distanceInMiles = route.distance * 0.000621371
            completion(distanceInMiles)
        }
    }
}

Usage Question

Class 2: How do I access the distance value in a different class? For example, I have a parameterized init, where the third parameter "dist" is of type CLLocationDistance. What I am trying to achieve is to access the distance value from the calculateDistance method of Class1

let assigningDistValue = Class1(coordinate: location, secondParam: paramValue, dist:finalDistance!)

I have pretty much read all suggested solutions related to this problem and nothing helped.

1

There are 1 best solutions below

1
On

You cannot access finalDistance after the closure, because the code runs in this order:

var finalDistance: CLLocationDistance?
// 1:
let calculatedDistance = Class1.calculateDistance(location, location2: secondlocation) { (distance) in
    // 3:
    guard let distanceInMiles = distance else { return }
    print("This is to print distance in miles", distanceInMiles)
    finalDistance = calculatedDistance
}
// 2:
let assigningDistValue = Class1(coordinate: location, secondParam: paramValue, dist:finalDistance!)

Just move the let line into the end of the asynchronous material:

let calculatedDistance = Class1.calculateDistance(location, location2: secondlocation) { (distance) in
    guard let distanceInMiles = distance else { return }
    print("This is to print distance in miles", distanceInMiles)
    finalDistance = calculatedDistance
    // put it here
    let assigningDistValue = Class1(coordinate: location, secondParam: paramValue, dist:finalDistance!) {
        // and on we go...
    }
}

Or else, use another completion block, just you did in the first code you showed. This is all correct in the first code, but then in the second code all that knowledge of what asynchronous means appears to be forgotten.