Networking (URLSession)
Networking (URLSession)
Fetch and send JSON over HTTPS using URLSession with async/await, and integrate responses into SwiftUI.
GET Request with async/await
Use URLSession.shared.data(from:) with async/await to fetch data.
Syntax:
let (data, response) = try await URLSession.shared.data(from: url)- decode with
JSONDecoder().decode
Example
import SwiftUI
import Foundation
struct Todo: Decodable, Identifiable { let id: Int; let title: String }
func fetchTodos() async throws -> [Todo] {
let url = URL(string: "https://jsonplaceholder.typicode.com/todos?_limit=2")!
let (data, _) = try await URLSession.shared.data(from: url)
return try JSONDecoder().decode([Todo].self, from: data)
}
struct NetworkingGetDemo: View {
@State private var todos: [Todo] = []
var body: some View {
List(todos) { t in Text(t.title) }
.task {
do { todos = try await fetchTodos() } catch { print(error) }
}
}
}
import SwiftUI
struct ContentView: View {
var body: some View { NetworkingGetDemo() }
}
import SwiftUI
@main
struct MyApp: App {
var body: some Scene {
WindowGroup { ContentView() }
}
}
This example fetches a small JSON list with URLSession using async/await and displays it in a SwiftUI List.
Sample App: Notes (Networking)
Use @MainActor class VM: ObservableObject { @Published var items: [T] = []; func loadFromAPI() async { ... } } to separate concerns and load data in the background.
Syntax:
@MainActor class VM: ObservableObject { @Published var items: [T] = []; func loadFromAPI() async { ... } }- View:
.task { await vm.loadFromAPI() }to kick off the async load - API:
let (data, _) = try await URLSession.shared.data(from: url),JSONDecoder().decode
Example
import SwiftUI
import Foundation
struct NoteDTO: Decodable, Identifiable { let id: Int; let title: String; let body: String }
enum API {
static func fetchNotes() async throws -> [NoteDTO] {
let url = URL(string: "https://jsonplaceholder.typicode.com/posts?_limit=3")!
let (data, _) = try await URLSession.shared.data(from: url)
return try JSONDecoder().decode([NoteDTO].self, from: data)
}
}
@MainActor
final class NotesViewModel: ObservableObject {
@Published var notes: [NoteDTO] = []
func loadFromAPI() async {
do { notes = try await API.fetchNotes() }
catch { print(error) }
}
}
struct NotesView: View {
@StateObject private var vm = NotesViewModel()
var body: some View {
List(vm.notes) { n in Text(n.title) }
.task { await vm.loadFromAPI() }
}
}
import SwiftUI
struct ContentView: View {
var body: some View { NotesView() }
}
import SwiftUI
@main
struct MyApp: App {
var body: some Scene {
WindowGroup { ContentView() }
}
}
This example separates concerns with an API helper and a ViewModel, then loads notes into a SwiftUI List on task.
POST JSON
Send JSON by encoding your payload and setting the request method and headers.
Syntax:
var req = URLRequest(url:)req.httpMethod = "POST"req.setValue("application/json", forHTTPHeaderField: "Content-Type")req.httpBody = try JSONEncoder().encode(payload)let (_, resp) = try await URLSession.shared.data(for: req)
Example
import SwiftUI
import Foundation
struct NewTodo: Encodable { let title: String; let completed: Bool }
func createTodo(_ todo: NewTodo) async throws -> Int {
let url = URL(string: "https://jsonplaceholder.typicode.com/todos")!
var req = URLRequest(url: url)
req.httpMethod = "POST"
req.setValue("application/json", forHTTPHeaderField: "Content-Type")
req.httpBody = try JSONEncoder().encode(todo)
let (_, resp) = try await URLSession.shared.data(for: req)
return (resp as? HTTPURLResponse)?.statusCode ?? 0
}
struct NetworkingPostDemo: View {
@State private var status: Int? = nil
var body: some View {
VStack(spacing: 12) {
Button("Create Todo") {
Task {
do { status = try await createTodo(NewTodo(title: "Demo", completed: false)) }
catch { print(error); status = nil }
}
}
if let status { Text("Status: \(status)") }
}
.padding()
}
}
import SwiftUI
struct ContentView: View {
var body: some View { NetworkingPostDemo() }
}
import SwiftUI
@main
struct MyApp: App {
var body: some Scene {
WindowGroup { ContentView() }
}
}
This example sends a JSON payload with a POST request and returns the HTTP status code from the response.
Tip: Add App Transport Security exceptions in Info.plist only when required.
Prefer HTTPS.