Let's think about it this way for a second
`URLSession` is iOS's built-in networking API (no need for a third-party library like Android's Retrofit — Apple provides it for you). In modern Swift (5.5+), combining it with `async`/`await` syntax is easier to read than callback-based code (`completion handler`) — `URLSession.shared.data(from: url)` is an `async` function, called with `try await`. You can decode the JSON response into a struct that conforms to `Codable` using `JSONDecoder`.
Let's connect this to a real-world scenario
If you define `struct WeatherResponse: Codable { let city: String; let tempCelsius: Double }` and write `func fetchWeather(city: String) async throws -> WeatherResponse { let url = URL(string: "https://api.example.com/weather?city=\(city)")!; let (data, _) = try await URLSession.shared.data(from: url); return try JSONDecoder().decode(WeatherResponse.self, from: data) }` — calling `Task { weather = try await fetchWeather(city: "Yangon") }` fetches the weather data from the API and displays it in your UI.
Let's look at it together
struct WeatherResponse: Codable {
let city: String
let tempCelsius: Double
}
func fetchWeather(city: String) async throws -> WeatherResponse {
let url = URL(string: "https://api.example.com/weather?city=\(city)")!
let (data, _) = try await URLSession.shared.data(from: url)
return try JSONDecoder().decode(WeatherResponse.self, from: data)
}$ let weather = try await fetchWeather(city: "Yangon")
// weather: WeatherResponse(city: "Yangon", tempCelsius: 32.0)5-minute try-it
Try defining your own `fetchWeather` function (pick any free public weather API), and design the `try await` calling pattern inside a `Task { }`.
A quick heads-up
If you hardcode an API key (secret) in your app code, it ends up in the app bundle and can be extracted by decompiling it — sensitive keys should be routed through a backend proxy server instead.