Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS

Lewis Edmonds
Lewis Edmonds
2,823 Points

Extract array from closure before prepare for segue - Swift

Hi,

I am building arrays inside a closure, but I need to pass these arrays through a segue. I am able to print the contents of the arrays from within the closure, but when I access the array from outside, it is always empty.

I have tried to use .reloadData() to update the arrays outside of the closure, but I can't seem to get it quite right. Dos anyone know if this is the correct approach?

Here is my code:

    var distances: [Double]
    var journeyTimes: [Double]


            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)
                } else {
                    print("Error!")
                }
            }

The print statements above produce results, and my prepare for segue carries distances and journeyTimes through, but they are always empty when I try to access them.

I think I need to update the distances and journeyTimes arrays before prepare for segue, outside of the closure, but I don't know how to do it.

Grateful for any help on this

Thanks

Lewis

1 Answer

Jari Koopman
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Jari Koopman
Python Web Development Techdegree Graduate 29,349 Points

Hi Lewis,

The problem here is that a closure will be handled async. This means that it's code will be ran on a background tread while the main app continues execution, so if you were to run your code like this:

class.valueName = "ValueName is not set yet"
class.someClosure { value?, error? in
    if let value = value {
        class.valueName = value
        print(class.valueName)
    }
}
print(class.valueName)

This would print out:

ValueName is not set yet
TheNewValueName

So, the values you send in the segue will always be nil/empty because the closure is not finished yet.

I don't know how your code is organised so I can't really point towards a solution at this point, but I hoped this at least gave you an idea as to why your code is behaving as it is.

If you need more help, feel free to reach out to me again!

Regards, Jari

Lewis Edmonds
Lewis Edmonds
2,823 Points

Thanks, Jari.

I have tried to use a dispatchGroup to reflect the async nature of the closure, and extract the array.

    myDispatchGroup.enter()

    for index in 0...collective { 

        let sourceLocation = MKPlacemark(coordinate: collective[index]) 

        let destinationLocation = MKPlacemark(coordinate: collective[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)
            } else {
                print("Error!")
            }

        }
    }

self.myDispatchGroup.leave()

I am trying to test this by printing the arrays (distances and journeyTimes) outside of my directions.calculate, but it still gives me empty arrays. Do I have these in the wrong place? Or is this not the best approach to take?

Thanks

Lewis