Multiple return in an async func

Hi everyone.

I'm quite a newbie with Swift async/await and I was wondering how to handle a case like this. Let's suppose I have an async func which executes a background task and, during the waiting, it returns an "empty state" value, like this:

func getAsyncString() async -> String {
  Task { @MainActor
    try await Task.sleep(until: .now + seconds(10))
    return "Hello world!"
  }
  return "Getting a string..."
}

By using this to value a @Published property in a ObservableObject, I noticed that Xcode stops (with a breakpoint) at "return Hello world!" but it does not update the Text in which I try to show the String.

From my understanding, when we mark an execution with "await" the outer func is suspended. Then, iOS decides when to resume it and executes the remaining code.

I'm using this func in this way:

Task {
  testString = await getAsyncString()
}

It looks like this Task does not exist anymore after 10 seconds (the sleep time), so the testString update fails?

Thank you in advance for your time.

Fundamentally, returns from within a Task aren't the same as returns from with your function. So your function starts the Task and then immediately returns. A function, by itself, can't do what you want here. You can accomplish what you want by updating the local state property rather than returning a value. I'll use an Observable type here (if you can support the latest OS, it can be easier), but the principle is the same for @Published.

@MainActor
@Observable
final class SomeObservable {
  var string = ""

  func getAsyncString() {
    string = "Getting a string..."
    Task {
      try await Task.sleep(until: .now + .seconds(10))
      string = "Hello world!"
    }
  }
}

This ensures the same value is updated over time so anything observing the value receives updates.

2 Likes

That's what I had supposed to: I can get rid of return in this case.
Thank you very much.