2016-09-26 3 views
0

Google의 장소 API를 사용하여 API 요청을 수행하는 기능이 있습니다. API 응답 데이터에서 값을 캡처하여 변수로 설정하려고합니다. 이 함수는 다른 함수 내부에서 호출됩니다. 그런 다음 그 변수에 액세스하려고 시도하지만 불행히도 변수에는 아직 값이 포함되어 있지 않습니다. 이것은 스레딩 문제인 것으로 보이지만이를 수정하는 방법을 모르겠습니다.API에서 가능한 신속한 스레딩 문제

업데이트 : 응답을 기반으로 코드를 업데이트했습니다. 불행히도 나는 여전히 API 요청의 값으로 변수에 액세스 할 수 없습니다. 완성 처리기를 사용하는 api 요청을 수행하는 함수를 다시 작성했습니다. mapView (mapView : GMSMapView!, didTapInfoWindowOfMarker marker : GMSMarker!)는 Google지도 프레임 워크의 함수입니다. 완료 처리기를 사용하려면 이것을 다시 작성해야합니까? API 요청과

가 // 변수

var website = "" 

// 코드

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

// I는 defaultSession 및 dataTask 이렇게 초기화.

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

네트워크 요청은 비동기식이므로 나머지 코드는 네트워크 요청이 완료되기 전에 실행됩니다. 'defaultSession.dataTaskWithURL'가 완성 블록을 넘겨주는 것과 같은 방식으로 completion 블록을 취하기 위해'getWebsite2' 함수를 작성해야합니다. –

+0

응답을 위해 Oleg와 감사합니다. 나는 현재 당신과 Oleg의 제안을 따르고 있으며 완료 핸들러를 사용하려고합니다. 알아 내면 업데이트를 게시 할 것입니다. – ray

+0

snipplet에서'defaultSession'이 초기화되는 방법이 명확하지 않습니다. 'NSURLSession.shared()'에 대한 로컬 참조라고 가정하면이 코드는 다른 스레드에서 실행되어 데이터 경합을 유발합니다. 'self.website = ...'를'dispatch_async (dispatch_get_main_queue()) {...} '클로저로 감쌀 필요가 있습니다. – 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을 사용해야합니다.