UIActivityIndicatorView not showing up when invoke

2019-03-02 14:25发布

I'm trying to show a spinner during a possibly lengthy action invoked by a button press, but I can't get it to show up. Here's my code:

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

It looks to me like the animation doesn't get shown when started from within the UI thread executing the button pressed (if I only start the animation in the button call without stopping, it starts to display as soon as the buttonPressed callback finishes). I tried to play around with dispatch_async but didn't get anywhere. Here's what I tried:

First:

    @IBAction func buttonPressed(sender: UIBarButtonItem) {

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

Second:

    @IBAction func buttonPressed(sender: UIBarButtonItem) {

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

    func shufflePlaylist() {

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

Third:

    @IBAction func buttonPressed(sender: UIBarButtonItem) {

        self.actInd.startAnimating()

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

    func shufflePlaylist() {

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

I run into the same problem when trying to show the spinner after the user deletes a table view row in (which also can trigger some lengthy data update operation) in commitEditingStyle.

So what's the right approach to show an activity indicator in those cases?

1条回答
Viruses.
2楼-- · 2019-03-02 15:10

What you want is something like:

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

This starts the spinner,then dispatches to a background thread, performs a task there (I'm assuming the task you are performing is one that can be performed on a background thread - i.e it doesn't involve UI stuff). Once the task is complete, the method dispatches back to the main UI thread, and stops the spinner.

查看更多
登录 后发表回答