Almost every modern iOS application needs to connect to the internet to fetch or send data.
Whether you are downloading user profiles, fetching live weather, or loading images, networking is a critical skill.
In Swift, the standard tool for making network requests is URLSession.
Combined with SwiftUI and Swift's modern async/await concurrency features, networking has never been easier.
Before fetching data from an API, you need a Swift structure to hold that data.
Most modern web APIs return data in JSON format.
To convert JSON into a Swift object automatically, your struct must conform to the Codable protocol.
import Foundation// Conforming to Codable allows automatic JSON translation // Conforming to Identifiable allows us to use it in SwiftUI Lists struct User: Codable, Identifiable { let id: Int let name: String let email: String }
To fetch data, you use URLSession.shared.data(from:).
Because network requests take time, you must use await to pause execution until the server responds.
Once the raw data arrives, you use a JSONDecoder to decode the data into your Codable struct.
func fetchUsers() async throws -> [User] {
// 1. Create a valid URL
guard let url = URL(string: "https://jsonplaceholder.typicode.com/users") else {
throw URLError(.badURL)
}
// 2. Fetch the data asynchronously
let (data, _) = try await URLSession.shared.data(from: url)
// 3. Decode the JSON data into an array of Users
let decodedUsers = try JSONDecoder().decode([User].self, from: data)
return decodedUsers
}
You cannot call an asynchronous function directly from a standard SwiftUI button or onAppear modifier.
Instead, SwiftUI provides the .task modifier.
The .task modifier automatically creates a new concurrent background task the exact moment the view appears on the screen.
import SwiftUIstruct UsersListView: View { @State private var users: [User] = [] var body: some View { List(users) { user in VStack(alignment: .leading) { Text(user.name).font(.headline) Text(user.email).font(.subheadline).foregroundColor(.gray) } } // This triggers automatically when the List appears! .task { do { users = try await fetchUsers() } catch { print("Error fetching users: \(error)") } } } }
If the view disappears before the network request finishes, SwiftUI automatically cancels the .task to save battery life!
Which protocol must your Swift struct conform to so that `JSONDecoder` can automatically map JSON data to its properties?