Je pratique avec DispatchQuue et la lutte toute la journée parce que le Swift s'est allé trop vite avant que l'API ne puisse finir d'écrire à la matrice. Ce que je remarque deux codes différents ci-dessous:
if let url = URL(string: "https://api.sunrise-sunset.org/json?lat=36.7201600&lng=-4.4203400&formatted=0") { URLSession.shared.dataTask(with: url) { data, response, error in if let data = data { do { let res = try JSONDecoder().decode(Response.self, from: data) let dateAPI = DateFormatter() dateAPI.locale = Locale(identifier: "en_US_POSIX") dateAPI.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ" let ss_rise_ast = dateAPI.date(from: res.results.astronomical_twilight_begin) let ss_rise_nau = dateAPI.date(from: res.results.nautical_twilight_begin) let ss_rise_civ = dateAPI.date(from: res.results.civil_twilight_begin) let ss_sunrise = dateAPI.date(from: res.results.sunrise) let ss_solar = dateAPI.date(from: res.results.solar_noon) let ss_sunset = dateAPI.date(from: res.results.sunset) let ss_set_civ = dateAPI.date(from: res.results.civil_twilight_end) let ss_sun_nau = dateAPI.date(from: res.results.nautical_twilight_end) let ss_sun_ast = dateAPI.date(from: res.results.astronomical_twilight_end) let dateToString = DateFormatter() dateToString.dateFormat = "h:mm a" let resultDate_ss_rise_ast = dateToString.string(from: ss_rise_ast!) let resultDate_ss_rise_nau = dateToString.string(from: ss_rise_nau!) let resultDate_ss_rise_civ = dateToString.string(from: ss_rise_civ!) let resultDate_ss_sunrise = dateToString.string(from: ss_sunrise!) let resultDate_ss_solar = dateToString.string(from: ss_solar!) let resultDate_ss_sunset = dateToString.string(from: ss_sunset!) let resultDate_ss_set_civ = dateToString.string(from: ss_set_civ!) let resultDate_ss_sun_nau = dateToString.string(from: ss_sun_nau!) let resultDate_ss_sun_ast = dateToString.string(from: ss_sun_ast!) if res.status == "OK" { self.sunrisesunsetString = [( ss_rise_ast: resultDate_ss_rise_ast, ss_rise_nau: resultDate_ss_rise_nau, ss_rise_civ: resultDate_ss_rise_civ, ss_sunrise: resultDate_ss_sunrise, ss_solar: resultDate_ss_solar, ss_sunset: resultDate_ss_sunset, ss_set_civ: resultDate_ss_set_civ, ss_sun_nau: resultDate_ss_sun_nau, ss_sun_ast: resultDate_ss_sun_ast, ss_timeday: res.results.day_length)] self.sunrisesunset1970 = [( ss_rise_ast: ss_rise_ast!.timeIntervalSince1970, ss_rise_nau: ss_rise_nau!.timeIntervalSince1970, ss_rise_civ: ss_rise_civ!.timeIntervalSince1970, ss_sunrise: ss_sunrise!.timeIntervalSince1970, ss_solar: ss_solar!.timeIntervalSince1970, ss_sunset: ss_sunset!.timeIntervalSince1970, ss_set_civ: ss_set_civ!.timeIntervalSince1970, ss_sun_nau: ss_sun_nau!.timeIntervalSince1970, ss_sun_ast: ss_sun_ast!.timeIntervalSince1970)] self.fetchingSunriseSunset.leave() } else { print("Error received API from Sunrise and Sunset") self.fetchingSunriseSunset.leave() } } catch let error { print(error) self.fetchingSunriseSunset.leave() } } }.resume() } }
3 Réponses :
Vous pouvez modifier la mise en œuvre de la méthode "FetchingSunserver" un peu comme ceci: Votre implémentation sera comme: p> Vous n'êtes pas obligé d'utiliser Dispatchgroup code> dans ce scénario alors. p> p>
Homme ... votre code est si parfaitement ......... incroyable. Merci!
Vous êtes définitivement sur le bon chemin, qui attend qu'un nombre défini de secondes n'est pas une bonne stratégie. Votre code devrait attendre jusqu'à ce que la récupération soit terminée, puis sur 3 secondes ait été passée, puis passez.
Dans votre deuxième exemple, il semble que vous puissiez être un peu confus autour de l'indentation et de la commande de Ce que vous faites. p>
La façon dont votre code est écrit maintenant, il dit essentiellement: p>
Clairement cela ne fonctionne pas, car on doit arriver avant l'autre. P>
J'imagine que votre problème est ici: P>
DispatchQueue.main.async { fetchingSunServer() // Start call the API to get sunrise and sunset time list fetchingSunriseSunset.leave() fetchingSunriseSunset.notify(queue: .main) { print("\(sunrisesunsetString.count)\n\(sunrisesunset1970.count)\nFinished create data.") } }
Le code se produit toujours dans "ordre", mais ce qui se passe dans l'ordre n'est pas la matière à l'intérieur du bloc ASYNC, plutôt la création de ce bloc. Et cela peut être un peu déroutant d'envelopper votre tête. P>
J'imagine ce que vous voulez réellement, est quelque chose de plus proche de ceci: p> la différence Voici petit mais important. p> Plutôt que de configurer l'appel ASYNC, puis vous allez imprimer, vous configurez maintenant l'appel ASYNC, pour aller imprimer lorsque le fetchingsUnserver () code> appel est fini. p> p>
Une meilleure approche serait d'utiliser Funciton FetchingsUnServer Déclaration: P> résultat code> type dans la fermeture. Et comme soupçonné, vous n'avez pas besoin d'utiliser
Dispatchgroup code>, car vous ne faites qu'un seul appel de l'API ici. Modifiez votre méthode comme celle-ci:
fetchingSunServer { (result) in
switch result {
case .success(let res):
let dateAPI = DateFormatter()
dateAPI.locale = Locale(identifier: "en_US_POSIX")
dateAPI.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
let ss_rise_ast = dateAPI.date(from: res.results.astronomical_twilight_begin)
let ss_rise_nau = dateAPI.date(from: res.results.nautical_twilight_begin)
let ss_rise_civ = dateAPI.date(from: res.results.civil_twilight_begin)
let ss_sunrise = dateAPI.date(from: res.results.sunrise)
let ss_solar = dateAPI.date(from: res.results.solar_noon)
let ss_sunset = dateAPI.date(from: res.results.sunset)
let ss_set_civ = dateAPI.date(from: res.results.civil_twilight_end)
let ss_sun_nau = dateAPI.date(from: res.results.nautical_twilight_end)
let ss_sun_ast = dateAPI.date(from: res.results.astronomical_twilight_end)
let dateToString = DateFormatter()
dateToString.dateFormat = "h:mm a"
let resultDate_ss_rise_ast = dateToString.string(from: ss_rise_ast!)
let resultDate_ss_rise_nau = dateToString.string(from: ss_rise_nau!)
let resultDate_ss_rise_civ = dateToString.string(from: ss_rise_civ!)
let resultDate_ss_sunrise = dateToString.string(from: ss_sunrise!)
let resultDate_ss_solar = dateToString.string(from: ss_solar!)
let resultDate_ss_sunset = dateToString.string(from: ss_sunset!)
let resultDate_ss_set_civ = dateToString.string(from: ss_set_civ!)
let resultDate_ss_sun_nau = dateToString.string(from: ss_sun_nau!)
let resultDate_ss_sun_ast = dateToString.string(from: ss_sun_ast!)
if res.status == "OK" {
self.sunrisesunsetString = [(
ss_rise_ast: resultDate_ss_rise_ast,
ss_rise_nau: resultDate_ss_rise_nau,
ss_rise_civ: resultDate_ss_rise_civ,
ss_sunrise: resultDate_ss_sunrise,
ss_solar: resultDate_ss_solar,
ss_sunset: resultDate_ss_sunset,
ss_set_civ: resultDate_ss_set_civ,
ss_sun_nau: resultDate_ss_sun_nau,
ss_sun_ast: resultDate_ss_sun_ast,
ss_timeday: res.results.day_length)]
self.sunrisesunset1970 = [(
ss_rise_ast: ss_rise_ast!.timeIntervalSince1970,
ss_rise_nau: ss_rise_nau!.timeIntervalSince1970,
ss_rise_civ: ss_rise_civ!.timeIntervalSince1970,
ss_sunrise: ss_sunrise!.timeIntervalSince1970,
ss_solar: ss_solar!.timeIntervalSince1970,
ss_sunset: ss_sunset!.timeIntervalSince1970,
ss_set_civ: ss_set_civ!.timeIntervalSince1970,
ss_sun_nau: ss_sun_nau!.timeIntervalSince1970,
ss_sun_ast: ss_sun_ast!.timeIntervalSince1970)]
print("\(sunrisesunsetString.count)\n\(sunrisesunset1970.count)\nFinished create data.")
} else {
print("Error received API from Sunrise and Sunset")
}
case .failure(let error):
print(error)
}
}
Erreur de préavis "L'utilisation de l'identifiant non résolu" res "et a découvert que j'ai laissé res = essayer jsondecoder (). Decode (réponse.fr de: Données) Mais votre spectacle achèvement (.success (Essayez JSondecoder (). Décode (réponse.fr de: Data))), Où devrais-je mettre "laisser res = ..."?
Ohhhhhh peu importe. Merci!!
Manquez ce bit, essayez d'utiliser les noms complets au lieu de formes courtes comme «res» qui font une bonne pratique de codage.
J'imprime le résultat et les deux tableaux encore zéro ... peut-être que j'ai mis un mauvais endroit? Où devrais-je mettre l'impression ou l'expédition ??
Ajoutez l'énoncé d'impression où je l'ai ajouté. Pas en dehors du bloc de fermeture. Si vous voulez que vous puissiez faire une autre fonction de fermeture ou une meilleure façon, c'est de faire un initialiseur de modèle. Mais l'affiché ici le ferait hors de portée.
POUVEZ UP, fonctionne parfaitement. Merci beaucoup.
Ajoutez votre code dans
FetchingsunServer CODE> ICI. Vous n'aurez probablement pas besoin d'un groupe de distribution, sauf si vous effectuez plusieurs appels d'API à la fois.
J'ai mis à jour. Fais-moi savoir