Swift 从 api 可能的线程问题中获取价值

Swift get value from api possible threading issue

我有一个函数可以使用 google 的位置 api 执行 api 请求。从 api 响应数据中,我捕获了一个值并尝试将其设置为一个变量。该函数在另一个函数内部被调用。然后我尝试访问该变量,但不幸的是该变量还不包含该值。这似乎是一个线程问题,但我不知道如何解决。

更新: 我已经根据响应更新了代码。不幸的是,我仍然无法使用 api 请求中的值访问变量。我重写了执行 api 请求的函数以使用完成处理程序。 mapView(mapView: GMSMapView!, didTapInfoWindowOfMarker marker: GMSMarker!) 是 google 地图框架中的一个函数。我是否也需要重写它才能使用完成处理程序?

//变量

var website = ""

// 带有 api 请求的代码

func getWebsite2(id: String, completion: (result: String) -> Void)  {

    var url = NSURL(string: "https://maps.googleapis.com/maps/api/place/details/json?placeid=\(id)&key=AIzaSyAWV1BUFv_vcedYroVrY7DWYuIxcHaqrv0")

    self.dataTask = defaultSession.dataTaskWithURL(url!) {
        data, respnse, error in
        let json : AnyObject
        do {
           json = try NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments)
            var dictionArr = json["result"]
            self.website = dictionArr!!["website"] as! String
            print(self.website)
        }
        catch {
            print(error)

        }
    }
    self.dataTask?.resume()
}

// 第二个函数

func mapView(mapView: GMSMapView!, didTapInfoWindowOfMarker marker: GMSMarker!) {

    let storeMarker = marker as! PlaceMarker

        self.getWebsite2(storeMarker.id!) {
            (result: String) in

            print("inside did tap")
            print(self.website)
            // problem still here 
           // above two lines of code never run
    }

    self.performSegueWithIdentifier("toWebView", sender: nil)
}

// 我这样初始化defaultSession和dataTask。

let defaultSession = NSURLSession(configuration:       NSURLSessionConfiguration.defaultSessionConfiguration())
var dataTask: NSURLSessionDataTask?

首先不要强制解包变量,并始终在需要的地方使用 do{} catch{}

这个小代码块展示了您应该如何处理 tryif let 条件:

   do {
        let jsonObject = try NSJSONSerialization.JSONObjectWithData(data, options: []) as! [String:AnyObject]
        if let dictionary = jsonObject["result"] as? [String: String] {
             self.website = dictionary["website"]
        } else {
             print("Parse error")
        }       
    } catch {
        print("JSON error: \(error)")
    }

其次defaultSession.dataTaskWithURL是异步请求,只有在他完成时才会设置数据。

在另一个世界中,您尝试在请求未完成时打印值。 为了解决你的问题,你应该使用 Completion Handlers.

您没有调用传递给 getWebsite2 函数的完成处理程序。此(伪)代码显示了如何获取从服务器接收到的字符串并将其传递给在 didTapInfoWindowOfMarker 中调用的闭包。

func getWebsite2(id: String, completion: (result: String) -> Void)  {

    self.dataTask = defaultSession.dataTaskWithURL(url!) {
    data, response, error in

        // now on background thread
        let someStringFromNetwork = data[0]

        dispatch_async(dispatch_get_main_queue(),{
            completion(someStringFromNetwork)
        })
    }
}