2016-09-26 21 views
0

我有一个函数,使用谷歌的地方api做api请求。从API响应数据中,我捕获一个值并尝试将其设置为一个变量。该功能在另一个功能中调用。然后我尝试访问该变量,但不幸的是该变量尚未包含该值。这似乎是一个线程问题,但我不知道如何解决它。Swift从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? 
+0

网络请求是异步的,所以其余的代码在网络请求完成之前运行。您需要编写函数'getWebsite2'来获取完成块,与'defaultSession.dataTaskWithURL'允许您传入完成块的方式相同 –

+0

感谢您和Oleg的回复。我目前正在跟踪你和Oleg的建议并尝试使用完成处理程序。我会在发现更新时发布更新 – ray

+0

不清楚如何从您的snipplet中初始化defaultSession。假设它是对'NSURLSession.shared()'的本地引用,代码将在不同的线程上运行并导致数据竞争。你需要在'dispatch_async(dispatch_get_main_queue()){...}'封闭中包装'self.website = ...'。 – user2378197

回答

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) 
     }) 
    } 
} 
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