Swift async method call for a command line app

Viewed 591

I'm trying to reuse some async marked code that works great in a SwiftUI application in a simple Swift-Command line tool. Lets assume for simplicity that I'd like to reuse a function

func fetchData(base : String) async throws -> SomeDate
    {
        let request = createURLRequest(forBase: base)
        
        let (data, response) = try await URLSession.shared.data(for: request)
        guard (response as? HTTPURLResponse)?.statusCode == 200 else {
            throw FetchError.urlResponse
        }
        let returnData = try! JSONDecoder().decode(SomeData.self, from: data)
        
        return returnData
    }

in my command line application. A call like

    let allInfo = try clerk.fetchData("base")

in my "main-function" gives the error message 'async' call in a function that does not support concurrency. What is the correct way to handle this case.

Thanks Patrick

2 Answers

To call an async method the call must take place inside an async method or wrapped in a Task.
Further the method must be called wirh await

Task {
    do {
        let allInfo = try await clerk.fetchData("base")
    } catch {
        print(error)
    }
}

You can make the entry point of the CLI async with this syntax

@main
struct CLI {
    static func main() async throws {

        let args = CommandLine.arguments
        ...
}

The name of the struct is arbitrary.

If you are using Argument Parser framework then from version 1.0 it supports async context. You have to make your struct conforms to protocol AsyncParsableCommand. It creates context in which async function can be run safely.

Related