Home > Software design >  How to use URLSession in MainActor
How to use URLSession in MainActor

Time:06-02

I have a ViewModel that is isolated with @MainActor and I assume that every part of this ViewModel class should run on the main actor (main thread), right?

So the question is, what about the async call of URLSession.shared.data?

Does it also run on main thread? Isn't that a bad approach?

@MainActor
class ViewModel {
    @Published var name: String = ""
    
    func fetchName() async {
        guard let (data, _) = try? await URLSession.shared.data(from: URL(string: "http://....")!),
              let response = try? JSONDecoder().decode(Response.self, from: data) else {
            return
        }
        
        self.name = response.name
    }
}

CodePudding user response:

Does it also run on main thread

No. That's the whole point of saying await. At that moment, the system can switch contexts to a background thread without you knowing or caring. Moreover, at await your code pauses without blocking — meaning that while you're waiting for the download, the main thread is free to do other work, the user can interact with your app, etc. Don't worry be happy.

CodePudding user response:

The issue is not the URLSession code that you await. That runs on a separate thread managed by URLSession. Whenever you see await, that means that the current execution is suspended while the asynchronous task runs, and that the current actor is free to run other code. All is well.

The only potential concern is code that runs synchronously on the main actor (i.e., everything besides what we await). In this case, the only relevant portion is the code after the await, inside what is called the “continuation”.

In this case, the continuation consists of the decode of the JSON and the updating of the property. That is modest and you are generally fine running that on the main actor.

But if the continuation consisted of anything anything more substantial (e.g. decoding many megabytes of JSON or decoding an image or the like), then you would want to move that off the main actor. But in this case, you are fine.

For more information, see WWDC 2021 video Swift concurrency: Behind the scenes.

  • Related