I created a simple, one screen iOS app with only two controls, an activity indicator and a button, as shown below. When I run the code, I get the "starting" message, and 5 seconds later, the "stopping" message, but the activity indicator just displays without spinning. I must be missing something basic. This has had me stumped for weeks.
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var activityIndicator: UIActivityIndicatorView!
@IBAction func startButton(_ sender: Any) {
activityIndicator.startAnimating()
print("starting")
sleep(5)
print("stopping")
activityIndicator.stopAnimating()
}
}
>Solution :
You are blocking the main thread and preventing any updates or interactions for 5 seconds. Screen does not refresh and in production your app would have been terminated by watchdog.
Try something like this:
@IBAction func startButton(_ sender: Any) {
let activityIndicator = self.activityIndicator
activityIndicator.startAnimating()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
activityIndicator.stopAnimating()
}
}
To explain on it there are multiple ways to skin this cat. But in general never block the main thread with anything. Either you have expensive operation or you are waiting for something you should do that on another thread.
Since you are just passing time there is no reason to use another thread. You can use a timer or dispatch queue. Timer would look like this:
@IBAction func startButton(_ sender: Any) {
let activityIndicator = self.activityIndicator
activityIndicator.startAnimating()
Timer.scheduledTimer(withTimeInterval: 5.0, repeats: false) { _ in
activityIndicator.stopAnimating()
}
}
But if you wanted to use another thread it would mean switching to another thread, waiting for 5 seconds (you could use sleep) and then switching back to main thread to stop the animation. So quite unideal to do.
I hope this gives you some more understanding on the topic.