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

时间:2016-09-26 12:53:06

标签: ios swift multithreading google-places

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

更新: 我已根据回复更新了代码。不幸的是,我仍然无法使用api请求中的值访问变量。我重写了执行api请求以使用完成处理程序的函数。 mapView(mapView:GMSMapView!,didTapInfoWindowOfMarker标记:GMSMarker!)是google maps框架中的一个函数。我是否需要重写这个以使用完成处理程序?

//变量

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?

2 个答案:

答案 0 :(得分:1)

您没有调用传递给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)
        })
    }
}

答案 1 :(得分:0)

首先,不要强行展开变量,并始终在需要的地方使用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