In App-Delegate, nachdem ich die Koordinaten des Benutzers mit Kernstandort abrufen möchte, möchte ich zwei API-Aufrufe vornehmen. Einer ist zu meinem Server, um eine Kugel des Stadtnamens zu bekommen, in dem wir uns befinden. Der Aufruf ist asynchron, also möchte ich den gesamten Inhalt in ein globales Variablenfeld laden, bevor ich den zweiten Aufruf von Google Maps api mache, um den Städtenamen von Google zu erhalten, auch mit einem Async-Aufruf. Und schließlich, nachdem ich alle Google-Daten geladen habe, möchte ich die beiden Arrays vergleichen, mit den Städtenamen einen Zufall finden. Um das zu tun, müssen die ersten beiden Operationen beendet sein. Dafür verwende ich Closures, um sicherzustellen, dass alle Daten vor dem nächsten Start geladen werden. Aber wenn ich mein Programm starte, findet es keinen Zufall zwischen den beiden Arrays und wenn ich Breakpoints setze, sehe ich, dass das zweite Array (google) geladen wird, nachdem der Vergleich gemacht wird, was sehr frustrierend ist, weil ich es habe Stellen Sie viele Schließungen ein, und zu diesem Zeitpunkt kann ich die Quelle meines Problems nicht finden. Jede Hilfe wäre willkommen.Schließungen in Swift tun was auch immer. Meine Codeausführung verhält sich nicht wie angenommen
dies AppDelegate:
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
}
Diese meine globalen Variablen swift Datei ist:
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()
dies ist die erste Funktion in AppDelegate genannt, die einen Anruf auf meinen Server machen zu laden die Stadt slug:
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!)
}
}
Dies ist die zweite Funktion, laden Sie Google-Inhalte, aber es ist ca gefüllt nach compareGoogleAndApiSlugs() und es sollte vor aufgerufen werden ...
/*
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!)
}
Und schließlich die Asynchron-Anrufe gibt es zwei, aber sie sind fast der gleiche Code:
/**
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()
}
Wenn jemand sehen das Problem oder ein wenig Licht werfen würde es sehr geschätzt werden.
Entschuldigung, können Sie etwas mehr erklären, was das Problem sein kann, wenn die Variable nicht atomar ist? Ich bin neu in Swift und diese Informationen können sehr hilfreich für mich sein. Möchten Sie auch nach dem globalen Variablenvervollständigungs-Handler fragen, er muss immer global sein? Gibt es nicht eine Möglichkeit, mit Einheimischen Komplementär zu machen? Möchte auch wissen, ob ich diese globalen Variablen wiederverwenden kann? Wie kann ich sie wieder auf false setzen? Und vielen Dank, denn deine Antwort hat mein Problem gelöst! – user3033437
Wenn die Variable nicht atomar ist und mehrere Threads gleichzeitig zum Schreiben darauf zugreifen, in welchem Zustand befindet sich die Variable noch? Jeder Thread kann einen anderen Wert sehen. Nein, Sie brauchen nicht immer globale Variablen. Tatsächlich brauchen Sie sie wahrscheinlich fast nie. Ja, Sie können sie wiederverwenden. – Brandon