Swift Networking

Making HTTP requests and handling network data

🌐 What is Swift Networking?

Swift networking involves making HTTP requests to web APIs, downloading data, and handling responses. URLSession is the primary framework for network operations in iOS apps.


// Simple GET request
let url = URL(string: "https://api.example.com/data")!
let task = URLSession.shared.dataTask(with: url) { data, response, error in
    // Handle response
}
task.resume()
                                    

Networking Components

🔗

URLSession

Main networking class

let session = URLSession.shared
// or custom configuration
📝

URLRequest

Configure HTTP requests

var request = URLRequest(url: url)
request.httpMethod = "POST"
📊

Data Tasks

Handle data responses

session.dataTask(with: request) {
    data, response, error in
}
🔄

JSON Parsing

Decode JSON responses

let decoder = JSONDecoder()
let result = try decoder.decode(Model.self, from: data)

🔹 Basic GET Request

Fetch data from a web API:

func fetchData() {
    guard let url = URL(string: "https://jsonplaceholder.typicode.com/posts/1") else {
        return
    }
    
    URLSession.shared.dataTask(with: url) { data, response, error in
        if let error = error {
            print("Error: \(error)")
            return
        }
        
        guard let data = data else {
            print("No data received")
            return
        }
        
        // Parse JSON
        do {
            let post = try JSONDecoder().decode(Post.self, from: data)
            print("Title: \(post.title)")
        } catch {
            print("JSON parsing error: \(error)")
        }
    }.resume()
}

🔹 POST Request with JSON

Send data to a server:

func postData() {
    guard let url = URL(string: "https://jsonplaceholder.typicode.com/posts") else {
        return
    }
    
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    
    let newPost = Post(title: "New Post", body: "Post content", userId: 1)
    
    do {
        let jsonData = try JSONEncoder().encode(newPost)
        request.httpBody = jsonData
        
        URLSession.shared.dataTask(with: request) { data, response, error in
            if let error = error {
                print("Error: \(error)")
                return
            }
            print("Post created successfully!")
        }.resume()
    } catch {
        print("Encoding error: \(error)")
    }
}

🔹 Data Models with Codable

Define models for JSON parsing:

struct Post: Codable {
    let id: Int?
    let title: String
    let body: String
    let userId: Int
}

struct User: Codable {
    let id: Int
    let name: String
    let email: String
    let phone: String?
    
    // Custom key mapping
    enum CodingKeys: String, CodingKey {
        case id
        case name
        case email
        case phone
    }
}

🔹 Error Handling

Handle network errors properly:

enum NetworkError: Error {
    case invalidURL
    case noData
    case decodingError
    case serverError(Int)
}

func fetchWithErrorHandling() {
    // ... URL setup ...
    
    URLSession.shared.dataTask(with: url) { data, response, error in
        if let error = error {
            print("Network error: \(error.localizedDescription)")
            return
        }
        
        guard let httpResponse = response as? HTTPURLResponse else {
            print("Invalid response")
            return
        }
        
        guard 200...299 ~= httpResponse.statusCode else {
            print("Server error: \(httpResponse.statusCode)")
            return
        }
        
        guard let data = data else {
            print("No data received")
            return
        }
        
        // Process data...
    }.resume()
}

🔹 Async/Await Networking

Modern Swift networking with async/await:

func fetchDataAsync() async throws -> Post {
    guard let url = URL(string: "https://jsonplaceholder.typicode.com/posts/1") else {
        throw NetworkError.invalidURL
    }
    
    let (data, response) = try await URLSession.shared.data(from: url)
    
    guard let httpResponse = response as? HTTPURLResponse,
          200...299 ~= httpResponse.statusCode else {
        throw NetworkError.serverError(0)
    }
    
    return try JSONDecoder().decode(Post.self, from: data)
}

// Usage
Task {
    do {
        let post = try await fetchDataAsync()
        print("Post title: \(post.title)")
    } catch {
        print("Error: \(error)")
    }
}

🧠 Test Your Knowledge

Which class is used for networking in Swift?