I want to do for-loop code with async. For simulating the async, I added some delays.
import Cocoa
class ViewController: NSViewController {
private let semaphore = DispatchSemaphore(value: 0)
private let concurrentQueue = DispatchQueue.global()
override func viewDidLoad() {
super.viewDidLoad()
for i in 1...10 {
if run(i) {
break
}
}
}
func run(_ i:Int) -> Bool{
let seed = arc4random()
let isSuccess = seed % 5 == 1
let delayInSeconds = Int(seed % 3)
concurrentQueue.asyncAfter(wallDeadline: .now() + .seconds(delayInSeconds)) {
DispatchQueue.main.async {
self.textView.string += "\(i)\t\(seed)\n"
}
self.semaphore.signal()
}
semaphore.wait()
return isSuccess
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
@IBOutlet var textView: NSTextView!
}
The problem is, when the code runs, all lines were added at once. I want it added one by one. Any idea?
The problem is solved. The reason that update UI part doesn't work is because that func run()
is running on main thread, which is blocked by semaphore.wait()
always. So to solve the problem, just added it to another thread.
override func viewDidLoad() {
super.viewDidLoad()
concurrentQueue.async {
for i in 1...10 {
if self.run(i) {
break
}
}
}
}