Swift’s async/await syntax simplifies asynchronous programming, allowing developers to write cleaner and more readable code. This feature, introduced in Swift 5.5, enables you to handle asynchronous tasks without the complexity of traditional callback mechanisms. Here are three diverse, practical examples that demonstrate how to use async/await in Swift.
In this example, we will fetch user data from a REST API. This is a common use case when building apps that require data from external sources.
To fetch data asynchronously, we define an asynchronous function that uses the URLSession
API.
import Foundation
struct User: Codable {
let id: Int
let name: String
}
func fetchUserData() async throws -> User {
let url = URL(string: "https://jsonplaceholder.typicode.com/users/1")!
let (data, _) = try await URLSession.shared.data(from: url)
let user = try JSONDecoder().decode(User.self, from: data)
return user
}
Task {
do {
let user = try await fetchUserData()
print("User: \(user.name)")
} catch {
print("Error fetching user data: \(error)")
}
}
This code defines a User
struct that conforms to Codable
, making it easy to decode JSON data. The fetchUserData
function performs a network request and decodes the response into a User
object.
do-catch
block.In this example, we will demonstrate how to run multiple asynchronous tasks in parallel. This can improve the performance of your applications when tasks are independent of each other.
We’ll fetch posts and comments from the API simultaneously.
import Foundation
struct Post: Codable {
let id: Int
let title: String
}
struct Comment: Codable {
let id: Int
let body: String
}
func fetchPosts() async throws -> [Post] {
let url = URL(string: "https://jsonplaceholder.typicode.com/posts")!
let (data, _) = try await URLSession.shared.data(from: url)
return try JSONDecoder().decode([Post].self, from: data)
}
func fetchComments() async throws -> [Comment] {
let url = URL(string: "https://jsonplaceholder.typicode.com/comments")!
let (data, _) = try await URLSession.shared.data(from: url)
return try JSONDecoder().decode([Comment].self, from: data)
}
Task {
do {
async let posts = fetchPosts()
async let comments = fetchComments()
let (fetchedPosts, fetchedComments) = try await (posts, comments)
print("Fetched \(fetchedPosts.count) posts and \(fetchedComments.count) comments.")
} catch {
print("Error fetching data: \(error)")
}
}
In this code, we use async let
to fetch posts and comments concurrently, allowing both operations to run simultaneously.
This example illustrates how to handle user input asynchronously in a SwiftUI application. We will simulate a user login process with a delay to represent a network call.
import SwiftUI
struct ContentView: View {
@State private var username: String = ""
@State private var isLoggedIn: Bool = false
@State private var errorMessage: String = ""
var body: some View {
VStack {
TextField("Username", text: $username)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
Button("Login") {
Task {
await loginUser(username: username)
}
}
.padding()
if isLoggedIn {
Text("Welcome, \(username)!")
} else if !errorMessage.isEmpty {
Text(errorMessage).foregroundColor(.red)
}
}
.padding()
}
func loginUser(username: String) async {
do {
// Simulate a network delay
try await Task.sleep(nanoseconds: 2 * 1_000_000_000)
// Basic validation
if username.isEmpty {
throw NSError(domain: "LoginError", code: 1, userInfo: [NSLocalizedDescriptionKey: "Username cannot be empty."])
}
// Simulate successful login
isLoggedIn = true
} catch let error as NSError {
errorMessage = error.localizedDescription
}
}
}
In this SwiftUI example, we create a simple login form. When the user presses the login button, the loginUser
function is called asynchronously, simulating a network operation with a delay.
Task.sleep
to simulate delays for demonstration purposes; in a real application, you would replace this with actual network calls.These examples demonstrate the versatility and power of Swift’s async/await syntax in various scenarios, making asynchronous programming more intuitive and maintainable.