Completion Handler

tk13hilltk13hill Membre
novembre 2018 modifié dans Objective-C, Swift, C, C++ #1

Bonjour à tous,

Cela fait plusieurs semaine que je n'arrive pas a trouver une solution stable concernant mon application.
Je fais plusieurs appel réseaux, j'utilise notamment Alamofire.
J'ai une requête qui me récupère un token (get), une fois mon token obtenu je fais un requête (post) avec le token, l'id et le mot de pass. Au niveau de ma connexion, j'ai trouvé mon application stable.

Une fois, la connexion réussi, j'accède au mon dashboard sous forme de Tab Bar Controller. C'est sur la premiere vue de mon Tab Bar controller que j'appelle une requête réseau, cette dernière contient l'ensemble des données pour l'ensemble de mon dashboard. J'ai d'abord essayé d'utilisé un dispatch group avec une queue dans l'appel réseau. Mais j'ai trouvé que l'application mettais un temps fou a chargé les données.

De plus, un autre problème, lors que je quitte la vue de mon tab bar controller pour accepter à une autre vue, je n'arrive pas a conserver les donné chargé dans la premiere. Comment je suis censé stocké mes données pour qu'elle soit accessibles sur l'ensemble de mes vues ?

Je sais pas trop si j'ai bien expliqué mon problème, je vous mets un exemple de mon code ci dessous.
Merci à vous.

    func initRequet() {
        Helper().alomofireGetImage(URL: "...") { content in

        self.profil = content.af_imageRoundedIntoCircle()
    }

    Helper().alomofireGet(URL: "...") { content in
        self.content = content

        print(content)
    }
}
    func alomofireGet(URL: String, onCompletion: @escaping ((_ response: JSON) -> Void)) {

    let header: HTTPHeaders = [
        "user": "...",
        "password": "..."
    ]

    var contentJSON = JSON()

    Alamofire.request(URL, headers: header).validate(statusCode: 200..<600).responseJSON() { (reponse) in
        if reponse.result.isSuccess {
            contentJSON = JSON(reponse.result.value!)
        } else {
            contentJSON = JSON(reponse.result.error!)
        }
        onCompletion(contentJSON)
    }
}
Mots clés:

Réponses

  • LarmeLarme Membre
    novembre 2018 modifié #2

    J'ai d'abord essayé d'utilisé un dispatch group avec une queue dans l'appel réseau. Mais j'ai trouvé que l'application mettais un temps fou a chargé les données.

    Voilà un point à clarifier.

    En général, tu vas utiliser un Dispatch_group si tu as plusieurs requêtes concurrentes et que tu souhaites attendre que toutes ces dernières soient terminées.
    Est-ce réellement ton cas ? Ou tu ne souhaites pas du tout ça.
    Un exemple c'est si tu dois télécharger deux images. As-tu réellement besoin que tu aies télécharger les deux pour les afficher, ou l'une peut s'afficher sans se soucier de savoir si l'autre est déjà affichée ou non.

    Dans le cas des données de ton dashboard, je suppose que tu dois télécharger ton dashboard, puis chacune des requêtes filles peut être indépendantes ?

    Pour la persistence de tes données (tant que l'application est alive), tu peux utiliser le pattern Singleton (en Swift/Objective-C, c'est en général appelé sharedInstance ou shared). Tu peux également passer exclusivement par le cache de tes requêtes.

  • Non les deux sont indépendantes mais je dois attendre qu'elles soit terminé afin de pouvoir afficher les informations sinon j'ai un message d'erreur (llbd).
    Exemple, ma première requête est une image, j'appelle cette requête dans mon view did load mais j'affiche cette photos également dans le view did load. Sans les dispatch group j'ai l'erreur (lldb) mais du coup mon app est au ralenti.

    Pour les données, une fois la connexion réussi, j'appelle une seul fois la requête qui contient l'ensemble des données. Le but c'est de plus la rappeler ou la rappeler mais de manière très fluide.

  • Non les deux sont indépendantes mais je dois attendre qu'elles soit terminé afin de pouvoir afficher les informations sinon j'ai un message d'erreur (llbd).

    Quelle message d'erreur ?
    Ce n'est pas clair, tu dois attendre ou non que toutes les requêtes soient terminées ?
    Si non, je pense que l'erreur est dans ton implémentation. Tu t'attends à des variables qui n'existent pas encore...

  • Bonjour Larme,

    Le message d'erreur que j'ai c'est un crash de l'application avec ce message : (lldb)
    Oui je dois attendre que les requêtes soient terminées.
    Mon procédé : le tout dans le view did load
    1 : Appel réseau, je récupère un JSON
    2 : A partir de ce JSON, je créais plusieurs object grace au contenu du JSON
    3 : J'affiche les éléments des différents objects.

    Merci à toi

  • LarmeLarme Membre
    novembre 2018 modifié #6

    Donc:
    1. Première requête « normale »
    2. Création d'un dispatch group pour ces requêtes.
    3. Fin du dispatch (notify), et tu modifies l'affichage.

    Si pour l'étape 2 tu as 2 requêtes, que l'une met 10 secondes, et l'autre 3 minutes, bah tu finiras l'étape 2 au bout de 3 minutes, on est bien d'accord ?

    En pseudo code:

    func firstRequest(onSuccess: (() -> Void)?) {
        webCall() { (paramRetour) in 
              onSuccess?()
        }
    }
    
    func secondStep(onEnd: (() -> Void)?) {
        let group = DispatchGroup()
    
        group.enter()
        webCall21() { (paramRetour) in 
            group.leave()
        }
    
        group.enter()
        webCall22() { (paramRetour) in 
            group.leave()
        }
    
        groupe.notify { 
            onEnd()
        }
    }
    
    func updateUI() {}
    

    Appel:

    func launchAll() {
        firstRequest(onSuccess: { 
            secondStep(onEnd: { 
                  updateUI()
            })
        }
    }
    
Connectez-vous ou Inscrivez-vous pour répondre.