0
votes

Swift Trop rapide Lisez et créez la matrice avant la fin de l'API Ecrire au tableau

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


2 commentaires

Ajoutez votre code dans FetchingsunServer 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


3 Réponses :


3
votes

Vous pouvez modifier la mise en œuvre de la méthode "FetchingSunserver" un peu comme ceci: xxx

Votre implémentation sera comme: xxx

Vous n'êtes pas obligé d'utiliser Dispatchgroup dans ce scénario alors.


1 commentaires

Homme ... votre code est si parfaitement ......... incroyable. Merci!



0
votes

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>

  • sortez sur un fil différent et récupérez les données. Li>
  • tandis que em> vous faites cela, notifiez le fil principal des données que vous avez. LI> ul>

    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.")
        }
    }
    
    • File d'attente de la file d'attente pour être effectuée (tout dans votre appel ASYNC) LI>
    • puis imprimez li> ul>

      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> xxx pré>

      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>


0 commentaires

-1
votes

Une meilleure approche serait d'utiliser 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:

Funciton FetchingsUnServer Déclaration: P>

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


6 commentaires

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.