swift 97 lines · 1 tab

URLSession networking with async/await

Sofia Martinez Jan 2026
1 tab
import Foundation

enum APIError: Error, LocalizedError {
    case invalidURL
    case invalidResponse
    case statusCode(Int)
    case decodingError(Error)
    case networkError(Error)

    var errorDescription: String? {
        switch self {
        case .invalidURL:
            return "Invalid URL"
        case .invalidResponse:
            return "Invalid response from server"
        case .statusCode(let code):
            return "Server returned status code \(code)"
        case .decodingError(let error):
            return "Failed to decode response: \(error.localizedDescription)"
        case .networkError(let error):
            return "Network error: \(error.localizedDescription)"
        }
    }
}

class APIService {
    static let shared = APIService()
    private let baseURL = "https://api.example.com"
    private let session: URLSession

    private init() {
        let configuration = URLSessionConfiguration.default
        configuration.timeoutIntervalForRequest = 30
        configuration.waitsForConnectivity = true
        self.session = URLSession(configuration: configuration)
    }

    func fetchPosts() async throws -> [Post] {
        guard let url = URL(string: "\(baseURL)/posts") else {
            throw APIError.invalidURL
        }

        do {
            let (data, response) = try await session.data(from: url)

            guard let httpResponse = response as? HTTPURLResponse else {
                throw APIError.invalidResponse
            }

            guard (200...299).contains(httpResponse.statusCode) else {
                throw APIError.statusCode(httpResponse.statusCode)
            }

            let decoder = JSONDecoder()
            decoder.keyDecodingStrategy = .convertFromSnakeCase

            do {
                let postsResponse = try decoder.decode(PostsResponse.self, from: data)
                return postsResponse.posts
            } catch {
                throw APIError.decodingError(error)
            }
        } catch let error as APIError {
            throw error
        } catch {
            throw APIError.networkError(error)
        }
    }

    func createPost(title: String, body: String) async throws -> Post {
        guard let url = URL(string: "\(baseURL)/posts") else {
            throw APIError.invalidURL
        }

        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.setValue("Bearer \(AuthManager.shared.token ?? "")", forHTTPHeaderField: "Authorization")

        let postData = CreatePostRequest(title: title, body: body)
        request.httpBody = try JSONEncoder().encode(postData)

        let (data, response) = try await session.data(for: request)

        guard let httpResponse = response as? HTTPURLResponse,
              (200...299).contains(httpResponse.statusCode) else {
            throw APIError.invalidResponse
        }

        return try JSONDecoder().decode(Post.self, from: data)
    }
}

struct CreatePostRequest: Encodable {
    let title: String
    let body: String
}
1 file · swift Explain with highlit

Modern Swift networking uses async/await for cleaner asynchronous code compared to completion handlers. URLSession's async methods like data(from:) make network calls straightforward. I wrap API calls in a service layer with typed responses using Codable. Error handling uses try/catch blocks instead of nested closures. For request configuration, I create URLRequest objects with custom headers, HTTP methods, and body data. Response validation checks status codes before decoding. Async/await integrates seamlessly with SwiftUI—mark view methods with async and call with Task. This modern approach eliminates callback hell and makes async code read linearly like synchronous code.


Related snips

typescript
export interface RetryOptions {
  retries: number;
  baseMs: number;
  maxMs: number;
  signal?: AbortSignal;
  onRetry?: (attempt: number, delay: number, err: unknown) => void;

Exponential backoff with jitter for retries

typescript reliability retry
by codesnips 2 tabs
javascript
// Creating a Promise
const myPromise = new Promise((resolve, reject) => {
  const success = true;

  setTimeout(() => {
    if (success) {

Promises and async/await patterns for asynchronous JavaScript

javascript promises async-await
by Alex Chang 1 tab
swift
import Combine
import Foundation

class SearchViewModel: ObservableObject {
    @Published var searchQuery = ""
    @Published var results: [SearchResult] = []

Combine operators for data transformation

swift combine reactive
by Sofia Martinez 1 tab
swift
import SwiftUI

struct ContentView: View {
    @State private var username = ""
    @State private var isLoggedIn = false
    @StateObject private var viewModel = LoginViewModel()

SwiftUI declarative UI with state management

swift swiftui ios
by Sofia Martinez 2 tabs
swift
import SwiftUI

struct CardModifier: ViewModifier {
    var backgroundColor: Color = .white
    var cornerRadius: CGFloat = 12
    var shadowRadius: CGFloat = 5

Custom SwiftUI view modifiers for reusability

swift swiftui ios
by Sofia Martinez 2 tabs
swift
import Foundation
import UIKit

class ImageProcessor {
    // Background processing with main thread updates
    func processImage(_ image: UIImage, completion: @escaping (UIImage?) -> Void) {

Grand Central Dispatch for concurrency

swift gcd concurrency
by Sofia Martinez 1 tab

Share this code

Here's the card — post it anywhere.

URLSession networking with async/await — share card
Link copied