Unlocking Swift's Concurrency Potential: Exploring async, throws, and await |
Async/await is a new feature in Swift that allows you to write asynchronous code in a more concise and readable way making it easier to work with tasks that may take time to complete, such as network requests, file I/O, or other async operations. It was introduced in Swift 5.5
What is asynchronous code?
Asynchronous code is code that can run concurrently with other code. This means that it can start running, and then pause while it waits for something to happen (such as a network request to complete), and then resume running when it is ready.
What is async/await?
Async/await is a way to write asynchronous code in Swift without having to use callbacks or completion handlers. It is a more concise and readable way to write asynchronous code, and it makes it easier to reason about how your code works.
How to use async/await
To use async/await, you first need to mark your function or method as asynchronous by adding the async keyword before the return type. You can also add the async keyword before a closure to indicate that it is asynchronous.
import SwiftUI struct ContentView: View { @State private var user: GitHubUser? var body: some View { VStack(spacing: 20) { AsyncImage(url: URL(string: user?.avatar_url ?? "https://avatars.githubusercontent.com/u/65787178?v=4")) { image in image .resizable() .aspectRatio(contentMode: .fit) .clipShape(Circle()) } placeholder: { Circle() .foregroundColor (.secondary) } .frame(width: 200, height: 200) Text (user?.login ?? "") .bold () .font (.title3) Text (user?.blog ?? "") .foregroundColor(.blue) .padding () .onTapGesture { let url = URL.init(string: user?.blog ?? "") guard let stackOverflowURL = url, UIApplication.shared.canOpenURL(stackOverflowURL) else { return } UIApplication.shared.open(stackOverflowURL) } Spacer() .padding () } .task { do { user = try await getUser() } catch GHError.invalidURL { print ("invalid URL") } catch GHError.invalidResponse { print ("invalid response") } catch GHError.invalidData { print ("invalid data") } catch { print ("unexpected error") } } } // Define an asynchronous function to make a network request func getUser() async throws -> GitHubUser { let endpoint = "https://api.github.com/users/appcodezip" guard let url = URL(string: endpoint) else { throw GHError.invalidURL } let (data, response) = try await URLSession.shared.data(from: url) guard let response = response as? HTTPURLResponse, response.statusCode == 200 else { throw GHError.invalidResponse } do { let decoder = JSONDecoder () decoder.keyDecodingStrategy = .convertFromSnakeCase return try decoder.decode (GitHubUser.self, from: data) } catch { throw GHError.invalidData } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
struct GitHubUser: Codable { let login: String? let avatar_url: String? let blog: String? enum CodingKeys: String, CodingKey { case login case avatar_url = "avatar_url" case blog } }
enum GHError: Error { case invalidURL case invalidResponse case invalidData }
0 Comments