Reputation: 197
Consider the following toy example
import SwiftUI
struct WeirdExample: View {
@State private var greetings = ["Hello", "Bye"]
@State private var count = 0
@State private var greetingIndex = 0
func modifyCount() {
count = (count + 1) % 100
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(150) , execute: modifyCount)
}
var body: some View {
VStack {
Spacer()
Text(greetings[greetingIndex])
Spacer()
Button("Change (maybe)"){
if count % 2 == 0 {
greetingIndex = (greetingIndex + 1) % 2
}
}
.padding()
}
.onAppear(){modifyCount()}
}
}
As far as I understand, everything in the example is running on the UI thread. However, I'm concerned by the fact that assigning to the count variable is not atomic. Is it conceivable to have a situation in which pressing the button catches that variable in a weird, undefined state? In other words, is an item dispatched to the main queue guaranteed to run uninterrupted until completion? Of course, being a serial queue guarantees that a job on the queue won't begin executing until the previous ones are finished running, but since there is a distinction between main thread and main queue, I wonder if there is reason for concern about this, or somehow the fact that everything is running on the main thread obviates any problems. Thanks.
Upvotes: 0
Views: 688
Reputation: 299345
but since there is a distinction between main thread and main queue.
The main queue is guaranteed to run on the main thread. It is also where the main RunLoop is, where @MainActor
things run, and where the main OperationQueue runs, and all of these things are serialized. While there is a difference between threads and queues (and you're wise to keep that in mind), "main" is the one case where all of the relevant things are equivalent. No, there is no race condition here.
Upvotes: 1