2016-01-17 4 views
1

J'essaye de montrer un spinner au cours d'une action éventuellement longue invoquée par un appui sur un bouton, mais je n'arrive pas à l'afficher. Voici mon code:UIActivityIndicatorAffichage n'apparaissant pas à l'appel de l'action du bouton

class ViewController: UIViewController { 

    var actInd : UIActivityIndicatorView! 
    [...] 

    override func viewDidLoad() { 

     super.viewDidLoad() 

     self.actInd = UIActivityIndicatorView(frame: CGRectMake(0,0, 50, 50)) as UIActivityIndicatorView 

     self.actInd.center = view.center 
     self.actInd.hidesWhenStopped = true 
     self.actInd.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.Gray 
     self.view.addSubview(actInd) 

     [...] 
    } 

    @IBAction func buttonPressed(sender: UIBarButtonItem) { 
     self.actInd.startAnimating() 
     // [...] do some work 
     self.actInd.stopAnimating() 
    } 
} 

Il me semble que l'animation ne sont pas présentés lors du démarrage à partir du thread d'interface utilisateur exécutant le bouton pressé (si je commence seulement l'animation dans l'appel de touche sans arrêt, il commence à afficher dès que le boutonAppel répété se termine). J'ai essayé de jouer avec dispatch_async mais je n'ai rien obtenu. Voici ce que j'ai essayé:

Première:

@IBAction func buttonPressed(sender: UIBarButtonItem) { 

     dispatch_async(dispatch_get_main_queue()) { 
      self.actInd.startAnimating() 
     } 
     shufflePlaylist() 
     dispatch_async(dispatch_get_main_queue()) { 
      self.actInd.stopAnimating() 
     } 
    } 

Deuxième:

@IBAction func buttonPressed(sender: UIBarButtonItem) { 

     dispatch_async(dispatch_get_main_queue()) { 
      shufflePlaylist() 
     } 
    } 

    func shufflePlaylist() { 

     self.actInd.startAnimating() 
     // [...] do the work 
     self.actInd.stopAnimating() 
    } 

Troisième:

@IBAction func buttonPressed(sender: UIBarButtonItem) { 

     self.actInd.startAnimating() 

     dispatch_async(dispatch_get_main_queue()) { 
      shufflePlaylist() 
     } 
    } 

    func shufflePlaylist() { 

     // [...] do the work 
     self.actInd.stopAnimating() 
    } 

je rencontre le même problème en essayant de montrer la fileuse après la l'utilisateur supprime une ligne de vue de la table (qui peut également déclencher une longue opération de mise à jour des données) dans commitEditingStyle.

Alors, quelle est la bonne approche pour montrer un indicateur d'activité dans ces cas?

+0

Que se passe-t-il exactement entre les appels de démarrage et d'arrêt? D'après ce que vous avez posté, il semble probable que le spinner démarre et s'arrête immédiatement parce que l'appel «do some work» est asynchrone. Vous avez mentionné que vous avez essayé d'utiliser 'dispatch_async' - pouvez-vous montrer ce que vous avez essayé? La pratique normale consiste à envoyer une file d'attente à un travailleur, à exécuter l'action requise de façon synchrone, puis à la renvoyer dans la file d'attente principale pour arrêter le tourneur - [ce tutoriel] (http://www.raywenderlich.com/79149/grand-central -dispatch-tutorial-swift-part-1) peut être utile –

+0

Le 'faire un peu de travail' se passe en réalité tous de façon synchrone dans le même thread (il fait quelques calculs et re-triera la source de données de la vue table). J'ai mis à jour mon post avec ce que j'ai essayé en utilisant 'dispatch_async' – dflachbart

Répondre

0

Qu'est-ce que vous voulez est quelque chose comme:

@IBAction func buttonPressed(sender: UIBarButtonItem) { 
    spinner.startAnimating() 
    let dispatchPriority = DISPATCH_QUEUE_PRIORITY_DEFAULT 
    dispatch_async(dispatch_get_global_queue(dispatchPriority, 0)) { 

    NSThread.sleepForTimeInterval(5.0) //your task here instead of this line 

    dispatch_async(dispatch_get_main_queue(), { 
     self.spinner.stopAnimating() 
    }) 
    } 
} 

Cela commence la fileuse, puis envoie à un fil d'arrière-plan, exécute une tâche là (je suppose la tâche que vous effectuez est celui qui peut être réalisée sur un thread d'arrière-plan - c'est-à-dire qu'il n'implique pas d'interface utilisateur). Une fois la tâche terminée, la méthode redistribue le thread principal de l'interface utilisateur et arrête le spinner.

+0

Génial, ça marche! Ma tâche consiste en fait à faire des choses sur l'interface utilisateur à la fin, mais j'ai trouvé que je peux déplacer cela aussi dans la distribution de la file d'attente principale où j'arrête le spinner. Merci! – dflachbart