''async' call in a function that does not support concurrency swift ios Xcode async/await

I'm trying to use async/await with Swift 5.5. I have my async function, but whenever I try to call it, I get this error:

'async' call in a function that does not support concurrency

Here's the code sample:

class TryThis {
    func getSomethingLater(_ number: Double) async -> String {
        // test - sleep for 3 seconds, then return
        Thread.sleep(forTimeInterval: 3)
        return String(format: ">>>%8.2f<<<", number)
    }
}

let tryThis = TryThis()

let result = await tryThis.getSomethingLater(3.141592653589793238462)
print("result: \(result)")

What's the solution for this??



Solution 1:[1]

The answer here is that the "await getSomethingLater" must be called from an async context. Literally that means changing this:

let result = await tryThis.getSomethingLater(3.141592653589793238462)
print("result: \(result)")

into this:

Task {
    let result = await tryThis.getSomethingLater(3.141592653589793238462)
    print("result: \(result)")
}

So the whole thing becomes:

class TryThis {
    func getSomethingLater(_ number: Double) async -> String {
        // test - sleep for 3 seconds, then return
        Thread.sleep(forTimeInterval: 3)
        return String(format: ">>>%8.2f<<<", number)
    }
}

let tryThis = TryThis()

Task {
    let result = await tryThis.getSomethingLater(3.141592653589793238462)
    print("result: \(result)")
}

Here's the output:

result: >>> 3.14<<<

There's great info in the Meet sync/await in Swift video from WWDC21.

Solution 2:[2]

When calling async code (including actor fields) from non-async code, you have to wrap it in a Task:

Task {
    let result = await tryThis.getSomethingLater(3.141592653589793238462)
    print("result: \(result)")
}

Further reading: Concurrency — The Swift Programming Language (Swift 5.5)

Solution 3:[3]

The original error is produced because "top-level" await is not yet supported in Swift (that is, code at the global scope). The error just means you need to provide the async function with an asynchronous context, like using Task, Task.detached or a TaskGroup, depending on the behaviour you want.

Task.detached {
    let result = await tryThis.getSomethingLater(3.141592653589793238462)
    print("result: \(result)")
}

However, your code snippet should work in the future when top-level await is eventually proposed, implemented and supported. Top-level await support was mentioned as part of the original proposal for async/await SE-0296.

Solution 4:[4]

In my case I just refactored the:

async { some-code-which-can-take-some-time }

with:

Task { some-code-which-can-take-some-time }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Bradley Mackey
Solution 2 Ky.
Solution 3
Solution 4 Ali Nawaz