I am currently learning about concurrency and would like to apply this knowledge to a basic calculation app I am developing. My goal is to ensure that two input calculation results are updated in real time, even while the calculations are being performed on a background thread.
However, my code doesn’t work and does not update the result in real-time. I would greatly appreciate your assistance in resolving these issues.
Thank you in advance for your help. Below is my code.
class DataModel: ObservableObject {
@Published var input1: Double? = nil
@Published var input2: Double? = nil
@Published var multiplication: Double = 0
@Published var input1by2: Double = 0
@Published var input2by1: Double = 0
func multiply() async {
guard
let input1 = input1,
let input2 = input2
else { return }
try? await Task.sleep(nanoseconds: 1000)
let value = input1 * input2
await MainActor.run {
self.multiplication = value
}
}
func division1() async {
guard
let input1 = input1,
let input2 = input2
else { return }
try? await Task.sleep(nanoseconds: 1000)
let value = input1 / input2
await MainActor.run {
self.input1by2 = value
}
}
func division2() async {
guard
let input1 = input1,
let input2 = input2
else { return }
try? await Task.sleep(nanoseconds: 1000)
let value = input2 / input1
await MainActor.run {
self.input2by1 = value
}
}
}
struct ContentView: View {
var body: some View {
ZStack {
VStack (spacing: 100) {
ResultView()
UserInput()
}
}
.padding()
}
}
struct ResultView: View {
@EnvironmentObject var tap: DataModel
var body: some View {
VStack(alignment: .leading, spacing: 10) {
HStack(spacing: 0) {
Text("Multiplication: ")
Text("(tap.multiplication, specifier: "%.2f")")
}
.task {
await tap.multiply()
}
HStack(spacing: 0) {
Text("Input1/Input2: ")
Text("(tap.input1by2, specifier: "%.2f")")
}
.task {
await tap.division1()
}
HStack(spacing: 0) {
Text("Input2/Input1: ")
Text("(tap.input2by1, specifier: "%.2f")")
}
.task {
await tap.division2()
}
}
.font(.title3)
.foregroundStyle(Color.primary)
}
}
struct UserInput: View {
@EnvironmentObject var tap: DataModel
var body: some View {
VStack(spacing: 20) {
HStack(spacing: 0) {
Text("Input 1: ")
.padding(.horizontal, 6)
TextField("123", value: $tap.input1, format: .number)
.foregroundStyle(Color.primary)
.keyboardType(.decimalPad)
}
.font(.headline)
.frame(width: 200, height: 35)
.background(
RoundedRectangle(cornerRadius: 10)
.stroke(Color.blue.gradient, lineWidth: 2)
)
HStack(spacing: 0) {
Text("Input 2: ")
.padding(.horizontal, 6)
TextField("123", value: $tap.input2, format: .number)
.foregroundStyle(Color.primary)
.keyboardType(.decimalPad)
}
.font(.headline)
.frame(width: 200, height: 35)
.background(
RoundedRectangle(cornerRadius: 10)
.stroke(Color.blue.gradient, lineWidth: 2)
)
}
}
}
4