Some functions inside `Task` closure becomes an async function in Swift

Advertisements

I’m not sure how is this being triggered, but sometimes when I call a function inside Task { } XCode gives an error that instructs me to add await in the called function.

Here’s a simplified instance I experienced:

public class Loader: UIView {
   

   
    public class func show(animated: Bool = true) {
        // showing the loader code
    }
}

enum Utilities {
    func doSomeAsyncTask(action: @escaping ()async->()) {
        Task {
            Loader.show() // XCode error: "Expression is 'async' but is not marked with 'await'"
            action()
        }      
    }
}

XCode shows the function is an async one

Does this have something to do that this is a class or something?

>Solution :

UIView is marked with the global actor @MainActor. Since Loader inherits from UIView, Loader is implicitly marked with @MainActor too.

This means that all the methods in Loader are isolated to the MainActor. The things in Task { ... } are not isolated to the MainActor. Therefore, to run a MainActor-isolated method in Task { ... }, you need to await for it. MainActor could be busy with something else at that time, and you’d need to wait for a bit before it runs show.

The methods that do not become async when you put them in Task { ... } are probably not isolated to a particular actor, e.g.

// not actor-isolated
func square(_ x: Int) -> Int { x * x }

enum Utilities {
    func doSomeAsyncTask(action: @escaping ()async->()) {
        Task {
            print(square(4)) // doesn't need async
            await action()
        }
    }
}

Leave a ReplyCancel reply