2016-06-12 5 views
0

응용 프로그램 대리인의 경우 코어 위치의 사용자 좌표를 가져온 후 두 번의 API 호출을 원합니다. 하나는 내 서버에, 우리가있는 도시 이름의 슬러그를 얻는 것입니다. 호출은 비동기이므로 전역 변수 배열에 모든 내용을로드하기 전에 google map api에 대한 두 번째 호출을 수행하여 async 호출을 사용하여 google에서 도시 이름을 가져 오려고합니다. 그리고 마지막으로 모든 Google 데이터를로드 한 후 두 개의 배열을 비교하고 도시 이름을 비교하여 우연의 일치를 찾습니다. 그렇게하기 위해서는 처음 두 작업이 끝났어야합니다. 이를 위해 클로저를 사용하여 다음 작업 시작 전에 모든 데이터가로드되는지 확인합니다. 하지만 내 프로그램을 시작할 때 두 개의 배열이 일치하지 않는 것을 발견하고 중단 점을 설정하면 두 번째 배열 (google)이로드됩니다. 후에 비교가 이루어 졌는데 이는 매우 불편합니다. 클로저를 많이 설정하고이 단계에서 내 문제의 출처를 찾을 수 없습니다. 어떤 도움을 주시면 감사하겠습니다.신속한 폐쇄가 무엇이든하고 있습니다. 내 코드 실행이 예상대로 작동하지 않습니다.

import Foundation 
import CoreLocation 
let weatherApiKey : String = "" //weather api key 
var globWeatherTemp : String = "" 
var globWeatherIcon : String = "" 
var globCity : String = "" 
var globCountry : String = "" 
let googleMapsApiKey : String = "" 
let googlePlacesApiKey : String = "" 
var TableData:Array<String> = Array <String>() 
var nsDict = [] 
var locValue : CLLocationCoordinate2D = CLLocationCoordinate2D() 


typealias SuccessClosure = (data: String?) -> (Void) 
typealias FinishedDownload =() ->() 
typealias complHandlerAsyncCall = (success : Bool) -> Void 
typealias complHandlerCitySlug = (success:Bool) -> Void 
typealias complHandlerAllShops = (success:Bool) -> Void 
typealias googleCompareSlugs = (success:Bool) -> Void 

var flagCitySlug : Bool? 
var flagAsyncCall : Bool? 
var flagAllShops : Bool? 

var values : [JsonArrayValues] = [] 
var citySlug : [SlugArrayValues] = [] 

var asyncJson : NSMutableArray = [] 
let googleJson : GoogleApiJson = GoogleApiJson() 

이로드 내 서버에 전화를 걸 애플 대리자에서 호출 된 첫 번째 함수입니다 : 이것은 내 전역 변수 신속한 파일입니다

let locationManager = CLLocationManager() 

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 
    // Override point for customization after application launch. 

    //Language detection 
    let pre = NSLocale.preferredLanguages()[0] 
    print("language= \(pre)") 

    //Core Location 
    // Ask for Authorisation from the User. 
    self.locationManager.requestAlwaysAuthorization() 

    //Clore Location 
    // For use in foreground 
    self.locationManager.requestWhenInUseAuthorization() 
    if CLLocationManager.locationServicesEnabled() { 
     locationManager.delegate = self 
     locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters 
     locationManager.startUpdatingLocation() 


     //Load cities slug via api call 
     let apiCall : webApi = webApi() 

     apiCall.loadCitySlugs(){(success) in 
      //Slug loaded in background 
      //Call google api to compare the slug 
      apiCall.loadGoogleContent(){(success) in //this function is called after compareGoogleAndApiSlugs() 
       apiCall.compareGoogleAndApiSlugs() //this one called before 
      } 
     } 

    } 
    return true 
} 

:

는 애플 대리자입니다 도시 슬러그 :

func loadCitySlugs(completed: complHandlerCitySlug){ 

    //Configure Url 
    self.setApiUrlToGetAllSlugs() 

    //Do Async call 
    asyncCall(userApiCallUrl){(success)in 

     //Reset Url Async call and Params 
     self.resetUrlApi() 

     //parse json 
     self.parseSlugJson(asyncJson) 

     flagCitySlug = true 
     completed(success: flagCitySlug!) 
    } 
} 

이것은 두 번째 기능으로, Google 콘텐츠를로드하지만 ca (compareGoogleAndApiSlugs 후 채워) 전에 호출해야하는데 ...

/* 
Parse a returned Json value from an Async call with google maps api Url 
*/ 
func loadGoogleContent(completed : complHandlerAsyncCall){ 

    //Url api 
    setGoogleApiUrl() 

    //Load google content 
    googleAsyncCall(userApiCallUrl){(success) in 

    //Reset API URL 
    self.resetUrlApi() 
    } 
    flagAsyncCall = true // true if download succeed,false otherwise 

    completed(success: flagAsyncCall!) 
} 

을 마지막으로 비동기 호출은 두가 있지만 거의 동일한 코드입니다 :

/** 
Simple async call. 
*/ 
func asyncCall(url : String, completed : complHandlerAsyncCall)/* -> AnyObject*/{ 

    //Set async call params 
    let request = NSMutableURLRequest(URL: NSURL(string: url)!) 
    request.HTTPMethod = "POST" 

    request.HTTPBody = postParam.dataUsingEncoding(NSUTF8StringEncoding) 
    let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in 
     guard error == nil && data != nil else { 
      // check for fundamental networking error 
      print("error=\(error)") 
      return 
     } 
     if let httpStatus = response as? NSHTTPURLResponse where httpStatus.statusCode != 200 { 
      // check for http errors 
      print("statusCode should be 200, but is \(httpStatus.statusCode)") 
      print("response = \(response)") 
     } 


     let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding) 

     asyncJson = responseString!.parseJSONString! as! NSMutableArray 

     flagAsyncCall = true // true if download succeed,false otherwise 

     completed(success: flagAsyncCall!) 

    } 
    task.resume() 

} 

사람이 볼 수 있다면 문제 또는 일부 빛을 던져 매우 감사하겠습니다. 상기 완료 블록이 googleAsyncCall 블록의 외측이라고

func loadGoogleContent(completed : complHandlerAsyncCall){ 

    setGoogleApiUrl() 
    googleAsyncCall(userApiCallUrl){(success) in 

     self.resetUrlApi() 
    } 
    flagAsyncCall = true 
    completed(success: flagAsyncCall!) //THIS LINE IS CALLED OUTSIDE THE googleAsyncCall.. 
} 

:

답변

1

문제는 이러한 기능이다.

코드가 있어야한다 :

func loadGoogleContent(completed : complHandlerAsyncCall){ 

    setGoogleApiUrl() 
    googleAsyncCall(userApiCallUrl){(success) in 

     self.resetUrlApi() 
     flagAsyncCall = true 
     completed(success: flagAsyncCall!) 

    } 
} 

이 Btw는 .. 글로벌 변수는 원자되지 않습니다 .. 그래서 조심.

+0

미안 변수가 원자가 아닌 경우 문제가 될 수있는 것에 대해 더 설명 할 수 있습니까? 나는 신속하고이 정보는 나를 위해 매우 도움이 될 수있는 새로운이야. 또한 글로벌 변수 완성 처리기에 대해 묻고 싶습니다. 항상 글로벌해야합니다. 현지인들과 함께 완성 처리사를 할 수있는 방법이 없을까요? 또한 전역 변수를 재사용 할 수 있는지 알고 싶습니다. 어떻게 다시 false로 설정할 수 있습니까? 감사합니다. 내 문제가 해결되었습니다. – user3033437

+0

변수가 원자가 아니고 여러 스레드가 동시에 쓰기를 위해 액세스하는 경우 변수는 여전히 있습니까? 각 스레드는 다른 값을 볼 수 있습니다. 아니요, 항상 전역 변수가 필요하지는 않습니다. 실제로, 당신은 거의 절대 필요 없을 것입니다. 예, 재사용 할 수 있습니다. – Brandon