@IBOutlet weak var Input: UITextField!
@IBOutlet weak var Heads: UILabel!
@IBOutlet weak var working: UIActivityIndicatorView!
@IBAction func Toss(_ sender: Any) {
DispatchQueue.global().sync {
//set up variables and method
var input = 0
func integer(from textField: UITextField) -> Int {
guard let text = textField.text, let number = Int(text) else {
return 0
}
return number
}
var runningTotal = 0
//collect input
input = integer(from: Input)
//start loading symbol
DispatchQueue.main.async() { [self] in
working.startAnimating()
}
//do math
for _ in 0..<input {
let currentTrial = Int.random(in: 0...1)
if(currentTrial == 1) {
runningTotal = 1
}
}
DispatchQueue.main.async { [self] in
//set output
Heads.text = String(runningTotal)
//stop loading symbol
working.stopAnimating()
}
}
}
This program calculates the number of heads flipped when conducting x coin flips (specified by the user). My activity spinner does not show up at all, even though it is set up to appear when animated. Any help would be appreciated!
CodePudding user response:
So, start by going and having a look at the documentation for DispatchQueue
The sync
function reads...
func sync(execute: () -> Void)
Submits a block object for execution and returns after that block finishes executing.
which is not what you want, this will block the main thread and prevent the UI from been updated.
Instead, what you want to use is one of the async
variants, for example...
func async(group: DispatchGroup?, qos: DispatchQoS, flags: DispatchWorkItemFlags, execute: () -> Void)
Schedules a block asynchronously for execution and optionally associates it with a dispatch group.
You should also get the input
value before you run the background thread, as you should avoid accessing components outside of the context of the main thread.
Runnable example...
class ViewController: UIViewController {
@IBOutlet weak var textField: UITextField!
@IBOutlet weak var working: UIActivityIndicatorView!
@IBOutlet weak var headsLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
headsLabel.isHidden = true
}
@IBAction func doStuff(_ sender: Any) {
var input = 0
func integer(from textField: UITextField) -> Int {
guard let text = textField.text, let number = Int(text) else {
return 0
}
return number
}
input = integer(from: textField)
working.startAnimating()
DispatchQueue.global(qos: .userInitiated).async {
//set up variables and method
var runningTotal = 0
//do math
for _ in 0..<input {
let currentTrial = Int.random(in: 0...1)
if(currentTrial == 1) {
runningTotal = 1
}
}
DispatchQueue.main.async { [self] in
headsLabel.isHidden = false
//set output
headsLabel.text = String(runningTotal)
//stop loading symbol
working.stopAnimating()
}
}
}
}