1

I'm trying to make an asynchronous network call using the async / await in Swift 5.5 but for some reason, it does not work as expected in my Swift Package.

let (data, response) = await URLSession.shared.data(for: request)

The above line of code works in a swift playground (request here being a URLRequest) but it fails to work inside my Swift Package (using swift tools version 5.5)

The error at first is: Type of expression is ambiguous without more context but I realized it had to do with the tuple assignment so I changed the statement to just:

let data = await URLSession.shared.data(for: request)

And it gives me the error: Value of type 'URLSession' has no member 'data'

Futhermore, Xcode's code completion does not list .data(for:) while working in the Swift Package as opposed to the playground. Check the screenshots below for a better understanding.

Swift Package Playground

Sabesh Bharathi
  • 171
  • 1
  • 9
  • You forgot the `await` keyword, and don't forget to do that call in an async context if you aren't in one already. `let (data, response) = await URLSession.shared.data` – Andy Ibanez Oct 17 '21 at 16:06
  • @AndyIbanez I forgot to add the `await` keyword here in the post, but it still doesn't work when I add it to the code. It produces the same errors. – Sabesh Bharathi Oct 17 '21 at 16:10

2 Answers2

1

I've done enough research and concluded that a Swift Package (which is universally built) requires macOS 12.0 SDK for Swift Concurrency, and the current Xcode 13 release does not have it. It is only on the betas, so I'd have to use the latest beta or wait until Apple announces an Xcode release that supports the macOS 12 SDK.

Sabesh Bharathi
  • 171
  • 1
  • 9
0

I'm surprised you didn't see the error

expression is 'async' but is not marked with 'await'

The function call URLSession.shared.data(for: request), because it's async, should return an asynchronous continuation instead of an (Data,URLResponse) tuple.

You would have two ways of handling that. You could immediately await the response as suggested in comments:

let (data, response) = await URLSession.shared.data(for: request)

or you could use async let to capture the continuation and then you can await it later:

async let requestTask = URLSession.shared.data(for: request)

print("Doing some other stuff")

let (data, response) = try await requestTask
Scott Thompson
  • 22,629
  • 4
  • 32
  • 34
  • I'm sorry about that, I forgot to type in the `await` keyword in the post, but I get the same errors even with the `await` keyword. The `async let` also does not work. The error is that, Swift fails to recognise the `data(for:)` method of URLSession. Works properly in a Playground but not in my Swift Package specifically. – Sabesh Bharathi Oct 17 '21 at 16:37
  • Then I'm afraid you're going to have to post more information about the Swift configuration in your package. Are your build settings set to use correct Swift version? Is the minimum supported iOS version set to 15 (or version flags used) etc. It seems your problem is not related to the code, but to how that code is compiled. – Scott Thompson Oct 17 '21 at 17:09
  • It works as expected in an iOS app, or a Playground. It even suggests to me to add the @available attribute on my iOS app project. It fails to recognize all that in my Swift Package. I am pretty sure I'm using swift-tools-version 5.5, and I even tried creating a new Swift Package (using latest Swift) and it doesn't seem to work in Swift Packages in general! – Sabesh Bharathi Oct 18 '21 at 04:03