Switch faster

Salut à  tous,


 


A l'aide d'un switch je change un état qui influence ma recherche de données qui s"affichent dans une tableView. La requête met quelques secondes à  s'exécuter et du coup l'animation du switch en met autant ce qui n'est pas très joli joli.


 


Voici un extrait de mon code :



var isDemoServer = false {
        didSet {
            loading(demo: isDemoServer)
        }
    }

 @IBAction func demoModeSwitch(sender: AnyObject) {        print ("switch")
        isDemoServer = demoSwitch.on
    }

L'IBAction est connecté à  valueChanged avec l'aide de storyboard.


 


D'avance merci


Mots clés:

Réponses

  • Comment ça ça mets du temps ?


    Tu bloques l'UI/main thread ?


    Qui d'avoir un mode qui switch, mais qui se mets en disabled/grisé tant que l'action n'a pas été validée (par un appel asynchrone par exemple), cela éviterait par la même occasions, deux requêtes rapides qui se contrediraient (et dont tu ne serais pas vraiment sûr de certifier quel est l'état final, enfin, ça serait perturbant pour l'utilisateur).


  • On dirait bien que tu bloques ton main thread en effet. Tu lances comment ta requête ?


  • L'idée de base c'est une classe reader qui parse de l'XML. J'ai aussi un protocole qui informe le délégué sur l'avancement. Pour le parse rien de bien méchant.


     


    Mais c'est effectivement par là  que ca bloque le main thread. Je souhaiterai que mes éléments s'affichent au fur et à  mesure qu'ils sont passé dans le parser XML



    protocol PodcastsReaderDelegate: class {
        func startReadingPodcastListDocument()
        func addPodcast (podcast: Podcast)
        func endReadingPodcastListDocument (withError error: NSError?)
        func errorInPodcastsListParser (error: NSError)
    }

    class PodcastsReader: NSObject, NSXMLParserDelegate {
        weak var delegate: PodcastsReaderDelegate?
  • iLandesiLandes Membre
    octobre 2016 modifié #5

    Dans mon ViewController je fais une mise à  jour avec ce code 



        func loadFeeds() {
            
            // UI enter in waiting mode
            podcasts = []
            activityIndicator.startAnimating()
            switchProductionDemoButton.enabled = false
            
            // Load podcast from XML
            reader.readFeeds(self.isDemo)

            // UI exit waiting mode
            activityIndicator.stopAnimating()
            switchProductionDemoButton.enabled = true
        }

    Mais a aucun moment je ne vois mon activityindicator et mon interface reste figé pendant le parse. Mon délégué (le viewcontroller) reçois tout d'un coup...


  • Ton xml tu le récupère bien sur un serveur ? Ou il est en local ?


     


    Toute processus qui peut bloquer le main thread doit être fait en fond. Tu dois lancer ta requête de cette façon et lorsqu'elle se termine mettre à  jour ton interface dans le thread principal.


  • Mon XML est sur un serveur.


     


    Tu as raison mais j'aimerai lancer le parse en arrière plan et mettre à  jour mon interface au fur et à  mesure que la requête récupère des informations. Je vois comment mettre une tache dans une autre queue mais pas comment elle peut communiquer avec l'interface


  • Avec des notifications par exemple.
  • Tu penses que cela marcherais mieux avec des notifications qu'avec mon protocol ?


  • LexxisLexxis Membre
    octobre 2016 modifié #10

    Tu peux invoquer ton code de mise à  jour avec un dispatch_async sur la main_queue (dispatch_get_main_queue) à  intervalle régulier pendant ton traitement. Tu peux aussi utiliser les notifications, comme le précise colas_, mais il me semble que les notifications sont traités à  partir du thread dans laquelle est ont été postés. Il convient donc de poster ces notification sur le main_thread.


     


    Tu as aussi la classe NSProgress qui est spécialement conçue pour ce genre de cas (il me semble).


  • @iLandes, je n'ai pas trop regardé ta solution donc je ne sais pas. Les notifications c'est un peu crade mais c'est parfois hyper utile quand tu veux pas te prendre la tête avec 10000 delegates.


     


    Pour le thread, ce que tu dis Lexxis est je crois vrai. Tu peux aussi à  la réponse de ta notification, lancer une méthode qui elle-même fait un dispatch_async vers le main thread.


  • J'utiliserais pas trop les notifications parce que je ne pense pas que ton cas s'y prête. Les notifications, tout le monde peut l'écouter or je pense pas que tu souhaites que ce soit le cas.


    Un délégué, ou mieux encore, un complétion block ou closure en swift fait bien l'affaire.


     


    Ce que je ne comprends pas par contre c'est le fur et à  mesure. Tu peux détailler ?


     


    Parce que, une fois que tu lances ta requête, ton interface ne met à  jour rien du tout car tu n'as encore aucun résultat. Tu veux mettre à  jour ton interface seulement une fois la requête terminée et le résultat parsé. Ce que fait en principe ta closure puisqu'elle va t'informer de la fin avec si tu passes un paramètre le Data associé.


  • Je suis d'accord je préfère les protocoles aux Notifications.


     


    Après relecture de mon code, je m'aperçois que pour parser de l'XML il faut lire le fichier (data) en entier. C'est cette opération qui prend du temps et qui bloque mon interface. Je dois donc mettre cela dans un queue à  part.


     


    Du coup cela remet en cause ce que je voulais faire : Signaler à  mon délégué que j'avais trouver un nouvel item dans mon parser XML. Ce qui est relativement rapide et ne bloque (pas trop l'interface).


     


    Merci à  tous pour votre aide.


Connectez-vous ou Inscrivez-vous pour répondre.