iOS Swift Hw用于访问在完成处理程序闭包中创建的数据 - 在闭包

时间:2015-07-06 21:25:25

标签: ios swift closures handler completion

我有一些使用

创建MapKit方向的代码
directions.calculateDirectionsWithCompletionHandler({(response, error) in

方法

代码工作正常 - 在完成处理程序中,但我无法弄清楚如何访问完成处理程序之外的数据。我已经定义了在完成处理程序之外使用的变量。

我意识到完成处理程序是异步运行的,但我不知道如何做以弥补这一点。

最后,提供的代码位于Swift Playground中,因为完成处理程序闭包在那里运行 - 在应用程序中,由于SSL错误,完成处理程序闭包永远不会运行。

这里的代码尽可能少:

//: Playground - noun: a place where people can play

import UIKit
import MapKit
import CoreLocation
import Contacts
import XCPlayground

XCPSetExecutionShouldContinueIndefinitely()

var directionsArray = [String]()
var addressString = ""

// Identify the Source and Destination
let source = MKMapItem(placemark: MKPlacemark(
    coordinate: CLLocationCoordinate2DMake(32.2345760,-110.8444420), addressDictionary: nil))
let destination = MKMapItem(placemark: MKPlacemark(
    coordinate: CLLocationCoordinate2DMake(34.104908,-118.137903), addressDictionary: nil))
let theLocation = CLLocation(latitude: source.placemark.coordinate.latitude, longitude: source.placemark.coordinate.longitude)

let directionsRequest = MKDirectionsRequest()
directionsRequest.source = source
directionsRequest.destination = destination
directionsRequest.requestsAlternateRoutes = true

let directions = MKDirections(request: directionsRequest)

print("before: directions.calculateDirectionsWithCompletionHandler addressString: \(addressString)")
print("before: directions.calculateDirectionsWithCompletionHandler directionsArray: \(directionsArray)")
directions.calculateDirectionsWithCompletionHandler({(response, error) in
    var selectedRoute = 1

    addressString += "\n source: 6922 E 1st St, 85710 Tucson, AZ United States"
    addressString += "\n Destination: 2014–2048 Huntington Dr, 91030 South Pasadena, CA United States"

    print("\nwithin: directions.calculateDirectionsWithCompletionHandler: \n")
    print("error: \(error)")
    print("response!.routes.count \(response!.routes.count)")
    print("response!.routes[selectedRoute] \(response!.routes[selectedRoute])")

    let theSteps = response?.routes[selectedRoute].steps.count as Int!

    print("theSteps: \(theSteps)")
    print("distance: \(response!.routes[selectedRoute].distance) meters") // time \(response?.routes.first?.time)")
    addressString += "\n distance: \(response!.routes[selectedRoute].distance) meters"
    let myRoute = response?.routes[selectedRoute]
    print("myRoute!.polyline.pointCount \(myRoute!.polyline.pointCount)")
    print("myRoute!.steps[0].polyline.points(): \(myRoute!.steps[0].polyline.points())")
    print("polyline.points \(myRoute!.polyline.points())")

    // Build an array of Route Step Coordinates for later inclusion in Directions
    var stepCoordinates = [CLLocationCoordinate2D]()
    for step in myRoute!.steps as [MKRouteStep] {
        let pointCount = step.polyline.pointCount
        var cArray = UnsafeMutablePointer<CLLocationCoordinate2D>.alloc(pointCount)
        step.polyline.getCoordinates(cArray, range: NSMakeRange(0, pointCount))

        for var c=0; c < pointCount; c++ {
            let coord = cArray[c]
            if c == 0 {
               var theCoordinate = CLLocationCoordinate2DMake(coord.latitude, coord.longitude)
            stepCoordinates.append(theCoordinate)
            }
        }
        cArray.dealloc(pointCount)
    }

    // get the Directions Steps including the latitidude / longitude from thearray of Step Coordinates
    for index in  0..<theSteps {
        let lat = stepCoordinates[index].latitude
        let lon = stepCoordinates[index].longitude
        directionsArray.append("\n steps[\(index)] \(lat),\(lon) - \(myRoute!.steps[index].distance) meters - \(myRoute!.steps[index].instructions)")
    }

    print("\nwithin: directions.calculateDirectionsWithCompletionHandler: addressString: \(addressString)")
    print("\nwithin: directions.calculateDirectionsWithCompletionHandler: directionsArray: \(directionsArray)")
})

print("\nafter: directions.calculateDirectionsWithCompletionHandler: addressString: \(addressString)")
print("after: directions.calculateDirectionsWithCompletionHandler: directionsArray: \(directionsArray)\n")

这是控制台输出:

之前:directions.calculateDirectionsWithCompletionHandler addressString:

before: directions.calculateDirectionsWithCompletionHandler directionsArray: []

after: directions.calculateDirectionsWithCompletionHandler: addressString: 
after: directions.calculateDirectionsWithCompletionHandler: directionsArray: []

2015-07-06 14:00:58.421 GetDirectionsBasic[9758:4735303] Failed to obtain sandbox extension for path=/var/folders/7l/cgpb6wr9489b1qhxl8y38hvm0000gn/T/com.apple.dt.Xcode.pg/containers/com.apple.dt.playground.stub.iOS_Simulator.GetDirectionsBasic-98692A18-CEBC-4354-8E6A-5B12BA647B9E/Library/Caches/com.apple.dt.playground.stub.iOS_Simulator.GetDirectionsBasic-98692A18-CEBC-4354-8E6A-5B12BA647B9E. Errno:1
2015-07-06 14:00:58.422 GetDirectionsBasic[9758:4735303] Failed to obtain sandbox extension for path=/var/folders/7l/cgpb6wr9489b1qhxl8y38hvm0000gn/T/com.apple.dt.Xcode.pg/containers/com.apple.dt.playground.stub.iOS_Simulator.GetDirectionsBasic-98692A18-CEBC-4354-8E6A-5B12BA647B9E/Library/Caches/com.apple.dt.playground.stub.iOS_Simulator.GetDirectionsBasic-98692A18-CEBC-4354-8E6A-5B12BA647B9E. Errno:1

within: directions.calculateDirectionsWithCompletionHandler: 

error: nil
response!.routes.count 3
response!.routes[selectedRoute] <MKRoute: 0x7fd7e0549220>
theSteps: 15
distance: 821009.0 meters
myRoute!.polyline.pointCount 2743
myRoute!.steps[0].polyline.points(): 0x00007fd7e1073000
polyline.points 0x00007fd7e1073000

within: directions.calculateDirectionsWithCompletionHandler: addressString: 
 source: 6922 E 1st St, 85710 Tucson, AZ United States
 Destination: 2014–2048 Huntington Dr, 91030 South Pasadena, CA United States
 distance: 821009.0 meters

within: directions.calculateDirectionsWithCompletionHandler: directionsArray: [
 steps[0] 32.2345979232341,-110.844443056463 - 0.0 meters - Proceed to E 1st St, 
 steps[1] 32.2345979232341,-110.844443056463 - 105.0 meters - At the end of the road, turn left onto N Green Hills Ave, 
 steps[2] 32.2345979232341,-110.843325078218 - 117.0 meters - Turn left onto E Speedway Blvd, 
 steps[3] 32.2356559708714,-110.843304039641 - 13216.0 meters - Turn right onto N Freeway Rd toward Phoenix, 
 steps[4] 32.235831990838,-110.983517018841 - 132.0 meters - Keep left to merge onto I-10 W, 
 steps[5] 32.236999925226,-110.9837630277 - 92506.0 meters - Take exit 199 to merge onto I-8 W toward San Diego, 
 steps[6] 32.8114569280297,-111.674388011842 - 374340.0 meters - Take exit 118B onto CA-111 N toward Indio, 
 steps[7] 32.773857973516,-115.495294079998 - 33287.0 meters - Turn right onto State Highway 86, 
 steps[8] 33.0002589616925,-115.585204073131 - 107741.0 meters - Continue onto I-10 W, 
 steps[9] 33.7204659450799,-116.19523705826 - 184120.0 meters - Keep left, 
 steps[10] 34.0650959406048,-118.013762030288 - 11125.0 meters - Take exit 23A onto Atlantic Blvd, 
 steps[11] 34.0716939233243,-118.132452042339 - 103.0 meters - Keep right on S Atlantic Blvd, 
 steps[12] 34.0717909857631,-118.133564069433 - 3815.0 meters - Turn left onto Garfield Ave, 
 steps[13] 34.1057089436799,-118.134696045456 - 108.0 meters - Turn left onto Huntington Dr, 
 steps[14] 34.1065149474889,-118.13535704234 - 294.0 meters - The destination is on your left]

3 个答案:

答案 0 :(得分:3)

你是对的,这里有一个关于异步性的根本问题。它实际上与MapKit或代码的大部分其他细节无关,所以我在后面的答案中抽象了它们。

&#34;异步&#34;意味着,对于任何看起来像这样的东西:

code with colored annotation

...绿色和蓝色块在 棕色块之前运行

execution order of colors

(另外,蓝色和棕色块之间的时间可以任意短或长,主线程在此期间更新UI。)

这意味着:

  • 蓝色块中的任何代码都不知道棕色块中发生的事情,因为它还没有发生。 (如果发生其他情况,你违反了因果关系......通知斯蒂芬霍金。并提交雷达。)

  • 由于棕色块中的代码需要从棕色块内触发,您想要发生的任何事情。 (或者来自其他地方,保证是&#34;之后&#34;。)

这也意味着,如果您正在尝试使用以下模式:

func getDirections() -> String {
    var directions: [String]
    getMKDirectionsWithCompletionHandler() { result, error in 
        directions = // something from result
    }
    return directions
}

......你的设计根本不可行。您需要查看要调用getDirections()函数的位置并使用其结果,并将它们设计为异步。

例如,如果你想做这样的事情:

let theDirections = getDirections()
destinationLabel.text = theDirections.last!

你需要做这样的事情:

getMKDirectionsWithCompletionHandler() { result, error in 
    let directions: [String] = // something from result
    destinationLabel.text = directions.last! // use it *in* the completion block
}

或者,请记住我的说法&#34;其他地方保证会更晚些时候&#34;?假设您要在表视图中显示这些字符串:

class MyViewController: UITableViewController {
    var directions = [String]()

    func viewWillAppear() {
        getMKDirectionsWithCompletionHandler() { result, error in 
            directions = // something from result

            // make sure the UI updates after we have our result
            self.tableView.reloadData() 
        }
    }

    func tableView(tv: UITableView, numberOfRowsInSection section: Int) -> Int {
        return directions.count
    }

    func tableView(tv: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let directionsItem = directions[indexPath.row]
        return // cell constructed from directionsItem
    }
}

答案 1 :(得分:1)

借助@matt的延迟例程和来自@ gooroo7的文件读/写例程,这是Playground中的一个工作示例......

由于启动获取路线请求时出现SSL握手问题,我无法让它在应用内运行:

mapDirections.calculateDirectionsWithCompletionHandler({(response, error) in

我已经包含了相当冗长的代码和控制台输出。来自@matt和@ gooroo7的例程记录在哪里使用。此外,控制台输出相当长 - 显示文件和使用的变量的之前,期间和之后(关闭)状态。

这是Playground代码:

//: Playground - noun: a place where people can play

import UIKit
import MapKit
import CoreLocation
import Contacts
import XCPlayground

XCPSetExecutionShouldContinueIndefinitely()

var directionsArray = [String]()
var addressString = String()

func setAddressString(theString:String){
    addressString = theString
    print("setAddressString \(addressString)")
}


// http://stackoverflow.com/questions/24097826/read-and-write-data-from-text-file
// answer by goroo7
//To avoid confusion and add ease, I have created two functions for reading and writing strings to files in the documents directory. Here are the functions:
//--------------------------------------------------------------------------------------------------------------
func writeToDocumentsFile(fileName:String,value:String) {
    let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] // as! NSString
    let path = documentsPath.stringByAppendingPathComponent(fileName)
    //    var error:NSError?
    do {
        try value.writeToFile(path, atomically: true, encoding: NSUTF8StringEncoding) //, error: nil)
    }
    catch let error as NSError {
        // Catch fires here, with an NSErrror being thrown from the value.writeToFile method
        print("A write to file error occurred, here are the details:\n \(error)")
    }
}

func readFromDocumentsFile(fileName:String) -> String {
    let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] //as! NSString
    let path = documentsPath.stringByAppendingPathComponent(fileName)
    let checkValidation = NSFileManager.defaultManager()
    //    var error:NSError?
    //    var file:String

    var file = ""
    if checkValidation.fileExistsAtPath(path) {
        do {
            try file = NSString(contentsOfFile: path, encoding: NSUTF8StringEncoding) as String
        }
        catch let error as NSError {
            // Catch fires here, with an NSErrror being thrown from the JSONObjectWithData method
            print("A read from file error occurred, here are the details:\n \(error)")
        }

    } else {
        file = "*ERROR* \(fileName) does not exist."
    }
    print("return file: \(file)")
    return file
}
//--------------------------------------------------------------------------------------------------------------


func getDirections() {
    print("getDirections")
    // Identify the Source and Destination
    let source = MKMapItem(placemark: MKPlacemark(
        coordinate: CLLocationCoordinate2DMake(32.2345760,-110.8444420), addressDictionary: nil))
    let destination = MKMapItem(placemark: MKPlacemark(
        coordinate: CLLocationCoordinate2DMake(34.104908,-118.137903), addressDictionary: nil))
    let theLocation = CLLocation(latitude: source.placemark.coordinate.latitude, longitude: source.placemark.coordinate.longitude)

    let directionsRequest = MKDirectionsRequest()
    directionsRequest.source = source
    directionsRequest.destination = destination
    directionsRequest.requestsAlternateRoutes = true

    let mapDirections = MKDirections(request: directionsRequest)

    print("before: directions.calculateDirectionsWithCompletionHandler addressString: \(addressString)")
    print("before: directions.calculateDirectionsWithCompletionHandler directionsArray: \(directionsArray)\n")
    mapDirections.calculateDirectionsWithCompletionHandler({(response, error) in
        let selectedRoute = 1

        let todaysDate:NSDate = NSDate()
        let dateFormatter:NSDateFormatter = NSDateFormatter()
        dateFormatter.dateFormat = "MM-dd-yyyy HH:mm"
        let DateInFormat:String = dateFormatter.stringFromDate(todaysDate)
        //print("\nDateInFormat: \(DateInFormat)\n")

        addressString = "\n..........addressString" //\n \(DateInFormat)"
        addressString += ("\n Date \(DateInFormat)")
        addressString += ("\n source: 6922 E 1st St, 85710 Tucson, AZ United States")
        addressString += ("\n Destination: 2014–2048 Huntington Dr, 91030 South Pasadena, CA United States")

        print("\nwithin: directions.calculateDirectionsWithCompletionHandler: \n")
        print("error: \(error)")
        print("response!.routes.count \(response!.routes.count)")
        print("response!.routes[selectedRoute] \(response!.routes[selectedRoute])")

        let theSteps = response?.routes[selectedRoute].steps.count as Int!

        print("theSteps: \(theSteps)")
        print("distance: \(response!.routes[selectedRoute].distance) meters") // time \(response?.routes.first?.time)")
        addressString += ("\n distance: \(response!.routes[selectedRoute].distance) meters")
        let myRoute = response?.routes[selectedRoute]
        print("myRoute!.polyline.pointCount \(myRoute!.polyline.pointCount)")
        print("myRoute!.steps[0].polyline.points(): \(myRoute!.steps[0].polyline.points())")
        print("polyline.points \(myRoute!.polyline.points())")

        // Build an array of Route Step Coordinates for later inclusion in Directions
        var stepCoordinates = [CLLocationCoordinate2D]()
        for step in myRoute!.steps as [MKRouteStep] {
            let pointCount = step.polyline.pointCount
            var cArray = UnsafeMutablePointer<CLLocationCoordinate2D>.alloc(pointCount)
            step.polyline.getCoordinates(cArray, range: NSMakeRange(0, pointCount))

            for var c=0; c < pointCount; c++ {
                let coord = cArray[c]
                if c == 0 {
                   var theCoordinate = CLLocationCoordinate2DMake(coord.latitude, coord.longitude)
                stepCoordinates.append(theCoordinate)
                }
            }
            cArray.dealloc(pointCount)
        }

        // get the Directions Steps including the latitidude / longitude from thearray of Step Coordinates
        for index in  0..<theSteps {
            let lat = stepCoordinates[index].latitude
            let lon = stepCoordinates[index].longitude
            directionsArray.append("\n steps[\(index)] \(lat),\(lon) - \(myRoute!.steps[index].distance) meters - \(myRoute!.steps[index].instructions)")
            addressString += ("\n steps[\(index)] \(lat),\(lon) - \(myRoute!.steps[index].distance) meters - \(myRoute!.steps[index].instructions)")

        }

        //        let directions: [String] = addressString
        setAddressString(addressString)
        print("\nwithin: directions.calculateDirectionsWithCompletionHandler: addressString: \(addressString)")
        print("\nwithin: directions.calculateDirectionsWithCompletionHandler: directionsArray: \(directionsArray)")


        // http://stackoverflow.com/questions/24097826/read-and-write-data-from-text-file
        // answer by goroo7
        //To avoid confusion and add ease, I have created two functions for reading and writing strings to files in the documents directory. Here are the functions: ... Here is an example of their use:
        //--------------------------------------------------------------------------------------------------------------
        writeToDocumentsFile("addressString.txt",value: addressString)
        //--------------------------------------------------------------------------------------------------------------

    })
}
getDirections()

// http://stackoverflow.com/questions/24034544/dispatch-after-gcd-in-swift/24318861#24318861
// answer by @matt
// I use dispatch_after so often that I wrote a top-level utility function to make the syntax simpler:
//--------------------------------------------------------------------------------------------------------------
func delay(delay:Double, closure:()->()) {
    dispatch_after(
        dispatch_time(
            DISPATCH_TIME_NOW,
            Int64(delay * Double(NSEC_PER_SEC))
        ),
        dispatch_get_main_queue(), closure)
}

//And now you can talk like this:

delay(3.0) {
    // do stuff
    let value = readFromDocumentsFile("addressString.txt")
    print("\nAfter Delay - readFromDocumentsFile written in closure: \(value)\n")  //Would output 'Hello world!'
    print("\nAfter Delay - read from external var addressString updated in closure: \(addressString)")
    print("\nAfter Delay - read from external var directionsArray updated in closure:\(directionsArray)")
}
//--------------------------------------------------------------------------------------------------------------

这是控制台输出:

getDirections
before: directions.calculateDirectionsWithCompletionHandler addressString: 
before: directions.calculateDirectionsWithCompletionHandler directionsArray: []

2015-07-07 16:12:31.116 GetDirectionsBasic[1768:630471] Failed to obtain sandbox extension for path=/var/folders/7l/cgpb6wr9489b1qhxl8y38hvm0000gn/T/com.apple.dt.Xcode.pg/containers/com.apple.dt.playground.stub.iOS_Simulator.GetDirectionsBasic-9B1F8F3C-4BBC-430F-AEFE-469C81A24CBE/Library/Caches/com.apple.dt.playground.stub.iOS_Simulator.GetDirectionsBasic-9B1F8F3C-4BBC-430F-AEFE-469C81A24CBE. Errno:1
2015-07-07 16:12:31.116 GetDirectionsBasic[1768:630471] Failed to obtain sandbox extension for path=/var/folders/7l/cgpb6wr9489b1qhxl8y38hvm0000gn/T/com.apple.dt.Xcode.pg/containers/com.apple.dt.playground.stub.iOS_Simulator.GetDirectionsBasic-9B1F8F3C-4BBC-430F-AEFE-469C81A24CBE/Library/Caches/com.apple.dt.playground.stub.iOS_Simulator.GetDirectionsBasic-9B1F8F3C-4BBC-430F-AEFE-469C81A24CBE. Errno:1

within: directions.calculateDirectionsWithCompletionHandler: 

error: nil
response!.routes.count 3
response!.routes[selectedRoute] <MKRoute: 0x7fed8a212e60>
theSteps: 15
distance: 821009.0 meters
myRoute!.polyline.pointCount 2743
myRoute!.steps[0].polyline.points(): 0x00007fed89052a00
polyline.points 0x00007fed89052a00
setAddressString 
..........addressString
 Date 07-07-2015 16:12
 source: 6922 E 1st St, 85710 Tucson, AZ United States
 Destination: 2014–2048 Huntington Dr, 91030 South Pasadena, CA United States
 distance: 821009.0 meters
 steps[0] 32.2345979232341,-110.844443056463 - 0.0 meters - Proceed to E 1st St
 steps[1] 32.2345979232341,-110.844443056463 - 105.0 meters - At the end of the road, turn left onto N Green Hills Ave
 steps[2] 32.2345979232341,-110.843325078218 - 117.0 meters - Turn left onto E Speedway Blvd
 steps[3] 32.2356559708714,-110.843304039641 - 13216.0 meters - Turn right onto N Freeway Rd toward Phoenix
 steps[4] 32.235831990838,-110.983517018841 - 132.0 meters - Keep left to merge onto I-10 W
 steps[5] 32.236999925226,-110.9837630277 - 92506.0 meters - Take exit 199 to merge onto I-8 W toward San Diego
 steps[6] 32.8114569280297,-111.674388011842 - 374340.0 meters - Take exit 118B onto CA-111 N toward Indio
 steps[7] 32.773857973516,-115.495294079998 - 33287.0 meters - Turn right onto State Highway 86
 steps[8] 33.0002589616925,-115.585204073131 - 107741.0 meters - Continue onto I-10 W
 steps[9] 33.7204659450799,-116.19523705826 - 184120.0 meters - Keep left
 steps[10] 34.0650959406048,-118.013762030288 - 11125.0 meters - Take exit 23A onto Atlantic Blvd
 steps[11] 34.0716939233243,-118.132452042339 - 103.0 meters - Keep right on S Atlantic Blvd
 steps[12] 34.0717909857631,-118.133564069433 - 3815.0 meters - Turn left onto Garfield Ave
 steps[13] 34.1057089436799,-118.134696045456 - 108.0 meters - Turn left onto Huntington Dr
 steps[14] 34.1065149474889,-118.13535704234 - 294.0 meters - The destination is on your left

within: directions.calculateDirectionsWithCompletionHandler: addressString: 
..........addressString
 Date 07-07-2015 16:12
 source: 6922 E 1st St, 85710 Tucson, AZ United States
 Destination: 2014–2048 Huntington Dr, 91030 South Pasadena, CA United States
 distance: 821009.0 meters
 steps[0] 32.2345979232341,-110.844443056463 - 0.0 meters - Proceed to E 1st St
 steps[1] 32.2345979232341,-110.844443056463 - 105.0 meters - At the end of the road, turn left onto N Green Hills Ave
 steps[2] 32.2345979232341,-110.843325078218 - 117.0 meters - Turn left onto E Speedway Blvd
 steps[3] 32.2356559708714,-110.843304039641 - 13216.0 meters - Turn right onto N Freeway Rd toward Phoenix
 steps[4] 32.235831990838,-110.983517018841 - 132.0 meters - Keep left to merge onto I-10 W
 steps[5] 32.236999925226,-110.9837630277 - 92506.0 meters - Take exit 199 to merge onto I-8 W toward San Diego
 steps[6] 32.8114569280297,-111.674388011842 - 374340.0 meters - Take exit 118B onto CA-111 N toward Indio
 steps[7] 32.773857973516,-115.495294079998 - 33287.0 meters - Turn right onto State Highway 86
 steps[8] 33.0002589616925,-115.585204073131 - 107741.0 meters - Continue onto I-10 W
 steps[9] 33.7204659450799,-116.19523705826 - 184120.0 meters - Keep left
 steps[10] 34.0650959406048,-118.013762030288 - 11125.0 meters - Take exit 23A onto Atlantic Blvd
 steps[11] 34.0716939233243,-118.132452042339 - 103.0 meters - Keep right on S Atlantic Blvd
 steps[12] 34.0717909857631,-118.133564069433 - 3815.0 meters - Turn left onto Garfield Ave
 steps[13] 34.1057089436799,-118.134696045456 - 108.0 meters - Turn left onto Huntington Dr
 steps[14] 34.1065149474889,-118.13535704234 - 294.0 meters - The destination is on your left

within: directions.calculateDirectionsWithCompletionHandler: directionsArray: [
 steps[0] 32.2345979232341,-110.844443056463 - 0.0 meters - Proceed to E 1st St, 
 steps[1] 32.2345979232341,-110.844443056463 - 105.0 meters - At the end of the road, turn left onto N Green Hills Ave, 
 steps[2] 32.2345979232341,-110.843325078218 - 117.0 meters - Turn left onto E Speedway Blvd, 
 steps[3] 32.2356559708714,-110.843304039641 - 13216.0 meters - Turn right onto N Freeway Rd toward Phoenix, 
 steps[4] 32.235831990838,-110.983517018841 - 132.0 meters - Keep left to merge onto I-10 W, 
 steps[5] 32.236999925226,-110.9837630277 - 92506.0 meters - Take exit 199 to merge onto I-8 W toward San Diego, 
 steps[6] 32.8114569280297,-111.674388011842 - 374340.0 meters - Take exit 118B onto CA-111 N toward Indio, 
 steps[7] 32.773857973516,-115.495294079998 - 33287.0 meters - Turn right onto State Highway 86, 
 steps[8] 33.0002589616925,-115.585204073131 - 107741.0 meters - Continue onto I-10 W, 
 steps[9] 33.7204659450799,-116.19523705826 - 184120.0 meters - Keep left, 
 steps[10] 34.0650959406048,-118.013762030288 - 11125.0 meters - Take exit 23A onto Atlantic Blvd, 
 steps[11] 34.0716939233243,-118.132452042339 - 103.0 meters - Keep right on S Atlantic Blvd, 
 steps[12] 34.0717909857631,-118.133564069433 - 3815.0 meters - Turn left onto Garfield Ave, 
 steps[13] 34.1057089436799,-118.134696045456 - 108.0 meters - Turn left onto Huntington Dr, 
 steps[14] 34.1065149474889,-118.13535704234 - 294.0 meters - The destination is on your left]
return file: 
..........addressString
 Date 07-07-2015 16:12
 source: 6922 E 1st St, 85710 Tucson, AZ United States
 Destination: 2014–2048 Huntington Dr, 91030 South Pasadena, CA United States
 distance: 821009.0 meters
 steps[0] 32.2345979232341,-110.844443056463 - 0.0 meters - Proceed to E 1st St
 steps[1] 32.2345979232341,-110.844443056463 - 105.0 meters - At the end of the road, turn left onto N Green Hills Ave
 steps[2] 32.2345979232341,-110.843325078218 - 117.0 meters - Turn left onto E Speedway Blvd
 steps[3] 32.2356559708714,-110.843304039641 - 13216.0 meters - Turn right onto N Freeway Rd toward Phoenix
 steps[4] 32.235831990838,-110.983517018841 - 132.0 meters - Keep left to merge onto I-10 W
 steps[5] 32.236999925226,-110.9837630277 - 92506.0 meters - Take exit 199 to merge onto I-8 W toward San Diego
 steps[6] 32.8114569280297,-111.674388011842 - 374340.0 meters - Take exit 118B onto CA-111 N toward Indio
 steps[7] 32.773857973516,-115.495294079998 - 33287.0 meters - Turn right onto State Highway 86
 steps[8] 33.0002589616925,-115.585204073131 - 107741.0 meters - Continue onto I-10 W
 steps[9] 33.7204659450799,-116.19523705826 - 184120.0 meters - Keep left
 steps[10] 34.0650959406048,-118.013762030288 - 11125.0 meters - Take exit 23A onto Atlantic Blvd
 steps[11] 34.0716939233243,-118.132452042339 - 103.0 meters - Keep right on S Atlantic Blvd
 steps[12] 34.0717909857631,-118.133564069433 - 3815.0 meters - Turn left onto Garfield Ave
 steps[13] 34.1057089436799,-118.134696045456 - 108.0 meters - Turn left onto Huntington Dr
 steps[14] 34.1065149474889,-118.13535704234 - 294.0 meters - The destination is on your left

After Delay - readFromDocumentsFile written in closure: 
..........addressString
 Date 07-07-2015 16:12
 source: 6922 E 1st St, 85710 Tucson, AZ United States
 Destination: 2014–2048 Huntington Dr, 91030 South Pasadena, CA United States
 distance: 821009.0 meters
 steps[0] 32.2345979232341,-110.844443056463 - 0.0 meters - Proceed to E 1st St
 steps[1] 32.2345979232341,-110.844443056463 - 105.0 meters - At the end of the road, turn left onto N Green Hills Ave
 steps[2] 32.2345979232341,-110.843325078218 - 117.0 meters - Turn left onto E Speedway Blvd
 steps[3] 32.2356559708714,-110.843304039641 - 13216.0 meters - Turn right onto N Freeway Rd toward Phoenix
 steps[4] 32.235831990838,-110.983517018841 - 132.0 meters - Keep left to merge onto I-10 W
 steps[5] 32.236999925226,-110.9837630277 - 92506.0 meters - Take exit 199 to merge onto I-8 W toward San Diego
 steps[6] 32.8114569280297,-111.674388011842 - 374340.0 meters - Take exit 118B onto CA-111 N toward Indio
 steps[7] 32.773857973516,-115.495294079998 - 33287.0 meters - Turn right onto State Highway 86
 steps[8] 33.0002589616925,-115.585204073131 - 107741.0 meters - Continue onto I-10 W
 steps[9] 33.7204659450799,-116.19523705826 - 184120.0 meters - Keep left
 steps[10] 34.0650959406048,-118.013762030288 - 11125.0 meters - Take exit 23A onto Atlantic Blvd
 steps[11] 34.0716939233243,-118.132452042339 - 103.0 meters - Keep right on S Atlantic Blvd
 steps[12] 34.0717909857631,-118.133564069433 - 3815.0 meters - Turn left onto Garfield Ave
 steps[13] 34.1057089436799,-118.134696045456 - 108.0 meters - Turn left onto Huntington Dr
 steps[14] 34.1065149474889,-118.13535704234 - 294.0 meters - The destination is on your left


After Delay - read from external var addressString updated in closure: 
..........addressString
 Date 07-07-2015 16:12
 source: 6922 E 1st St, 85710 Tucson, AZ United States
 Destination: 2014–2048 Huntington Dr, 91030 South Pasadena, CA United States
 distance: 821009.0 meters
 steps[0] 32.2345979232341,-110.844443056463 - 0.0 meters - Proceed to E 1st St
 steps[1] 32.2345979232341,-110.844443056463 - 105.0 meters - At the end of the road, turn left onto N Green Hills Ave
 steps[2] 32.2345979232341,-110.843325078218 - 117.0 meters - Turn left onto E Speedway Blvd
 steps[3] 32.2356559708714,-110.843304039641 - 13216.0 meters - Turn right onto N Freeway Rd toward Phoenix
 steps[4] 32.235831990838,-110.983517018841 - 132.0 meters - Keep left to merge onto I-10 W
 steps[5] 32.236999925226,-110.9837630277 - 92506.0 meters - Take exit 199 to merge onto I-8 W toward San Diego
 steps[6] 32.8114569280297,-111.674388011842 - 374340.0 meters - Take exit 118B onto CA-111 N toward Indio
 steps[7] 32.773857973516,-115.495294079998 - 33287.0 meters - Turn right onto State Highway 86
 steps[8] 33.0002589616925,-115.585204073131 - 107741.0 meters - Continue onto I-10 W
 steps[9] 33.7204659450799,-116.19523705826 - 184120.0 meters - Keep left
 steps[10] 34.0650959406048,-118.013762030288 - 11125.0 meters - Take exit 23A onto Atlantic Blvd
 steps[11] 34.0716939233243,-118.132452042339 - 103.0 meters - Keep right on S Atlantic Blvd
 steps[12] 34.0717909857631,-118.133564069433 - 3815.0 meters - Turn left onto Garfield Ave
 steps[13] 34.1057089436799,-118.134696045456 - 108.0 meters - Turn left onto Huntington Dr
 steps[14] 34.1065149474889,-118.13535704234 - 294.0 meters - The destination is on your left

After Delay - read from external var directionsArray updated in closure:[
 steps[0] 32.2345979232341,-110.844443056463 - 0.0 meters - Proceed to E 1st St, 
 steps[1] 32.2345979232341,-110.844443056463 - 105.0 meters - At the end of the road, turn left onto N Green Hills Ave, 
 steps[2] 32.2345979232341,-110.843325078218 - 117.0 meters - Turn left onto E Speedway Blvd, 
 steps[3] 32.2356559708714,-110.843304039641 - 13216.0 meters - Turn right onto N Freeway Rd toward Phoenix, 
 steps[4] 32.235831990838,-110.983517018841 - 132.0 meters - Keep left to merge onto I-10 W, 
 steps[5] 32.236999925226,-110.9837630277 - 92506.0 meters - Take exit 199 to merge onto I-8 W toward San Diego, 
 steps[6] 32.8114569280297,-111.674388011842 - 374340.0 meters - Take exit 118B onto CA-111 N toward Indio, 
 steps[7] 32.773857973516,-115.495294079998 - 33287.0 meters - Turn right onto State Highway 86, 
 steps[8] 33.0002589616925,-115.585204073131 - 107741.0 meters - Continue onto I-10 W, 
 steps[9] 33.7204659450799,-116.19523705826 - 184120.0 meters - Keep left, 
 steps[10] 34.0650959406048,-118.013762030288 - 11125.0 meters - Take exit 23A onto Atlantic Blvd, 
 steps[11] 34.0716939233243,-118.132452042339 - 103.0 meters - Keep right on S Atlantic Blvd, 
 steps[12] 34.0717909857631,-118.133564069433 - 3815.0 meters - Turn left onto Garfield Ave, 
 steps[13] 34.1057089436799,-118.134696045456 - 108.0 meters - Turn left onto Huntington Dr, 
 steps[14] 34.1065149474889,-118.13535704234 - 294.0 meters - The destination is on your left]

感谢所有帮助过的人 - 希望这对其他人有用!

答案 2 :(得分:0)

由于完成处理程序在另一个线程上运行,因此dispatch_async到您要在完成处理程序内部使用数据的线程。这样,您将在实际到达后访问数据。