Working with APIs

By the end of this lesson you'll fetch real data from the internet with URLSession , turn JSON into Swift types with Codable , handle failures cleanly with do/try/catch , and show the result in a SwiftUI view — the skill that turns a static app into a live one.

Learn Working with APIs in our free Swift course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.

Part of the free Swift course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

What You'll Learn in This Lesson

1️⃣ Codable — Turning JSON Into Swift Types

APIs speak JSON — plain text like {' "id": 1, "title": "Hello" '} . To use it, you describe its shape with a model (a struct ) and mark it Codable . That one word lets JSONDecoder read the text and fill in your struct automatically — every property name must match a JSON key, with the matching type. Read this worked example and run it; it needs no network.

2️⃣ URLSession + async/await — Fetching Over the Network

URLSession is Swift's built-in networking tool. The modern way to use it is async/await : you write try await URLSession.shared.data(from: url) and the line pauses until the bytes arrive, then carries on — reading top-to-bottom like ordinary code, with no nested callbacks. URL(string:) returns an Optional, so unwrap it safely, and remember URLSession only throws for transport errors — you check the HTTP status yourself.

Your turn. Below, the JSON and the calls are written for you — fill in the four ___ blanks marked with // 👉 to make the model and the decode work.

3️⃣ Error Handling — do / try / catch

Networking fails all the time — no signal, a typo in a URL, a server hiccup. Swift makes that explicit: a function that can fail is marked throws , you call it with try , and you wrap the call in do {' … '} catch {' … '} so a failure becomes a message instead of a crash. Inside catch , the thing that went wrong is available as error .

Now you try. This function is missing the three concurrency/error keywords. Fill in the three ___ blanks so it suspends, fetches, and handles failure.

4️⃣ Using the Data in SwiftUI with .task

A view that shows live data stores it in @State and loads it when it appears. The .task {' … '} modifier runs async code as the view shows up and cancels it automatically if the view disappears — so prefer it over .onAppear for loading. Code inside .task already runs on the main actor, so assigning to @State there updates the UI safely.

Sequential await calls wait for each other. When requests are independent, async let starts them all at once so the screen loads faster:

For snake_case APIs, skip hand-written CodingKeys with one line: decoder.keyDecodingStrategy = .convertFromSnakeCase maps first_name to firstName for the whole response.

📋 Quick Reference — Networking & JSON

No blanks this time — just a brief and an outline. Put together everything from this lesson: a Codable model, an async throws fetch, and a do/catch . Build it in Xcode and check your output against the expected line in the comments.

This was the final Swift lesson. Here's what you can now do:

Where to go next: wire this into a real app idea. Persist data with SwiftData or Core Data, add pull-to-refresh and loading states, structure logic into an MVVM view model, then publish to TestFlight . Practise by building a weather, news, or GitHub-search app against a free public API — you now have every piece you need.

Practice quiz

Which protocol lets a struct map to and from JSON?

  • Codable
  • Serializable
  • JSONMappable
  • Decoder

Answer: Codable. Conforming to Codable enables automatic JSON encoding and decoding.

Which type reads JSON bytes into a Swift value?

  • JSONReader
  • JSONDecoder
  • JSONParser
  • Decoder.shared

Answer: JSONDecoder. JSONDecoder().decode(...) turns Data into your model.

Which keyword marks a function that can pause for async work?

  • throws
  • defer
  • async
  • lazy

Answer: async. async marks a function that can suspend while awaiting results.

What does await do in a networking call?

  • Throws an error
  • Declares a constant
  • Retries the request
  • Suspends until the result arrives

Answer: Suspends until the result arrives. await pauses the function until the async result is ready.

Does URLSession throw an error on a 404 response?

  • No, you must check the status code yourself
  • Yes, always
  • Only on 500
  • Only without internet

Answer: No, you must check the status code yourself. URLSession only throws for transport errors; check statusCode == 200 yourself.

Which construct handles a thrown error safely?

  • if let / else
  • do / try / catch
  • guard / return
  • switch / default

Answer: do / try / catch. do { try ... } catch { ... } catches errors instead of crashing.

What does URL(string:) return?

  • A String
  • A Data value
  • An Optional URL
  • An error

Answer: An Optional URL. URL(string:) is failable and returns an optional, so unwrap it safely.

Which keyword marks a call inside catch-able code that may fail?

  • catch
  • async
  • await
  • try

Answer: try. try marks the exact call that may throw an error.

Which SwiftUI modifier runs async loading when a view appears?

  • .task
  • .onTap
  • .refreshable
  • .async

Answer: .task. .task runs async code on appear and auto-cancels on disappear.

What do you pass to decode to name the target type?

  • Post()
  • Post
  • Post.self
  • "Post"

Answer: Post.self. Pass the type itself, e.g. Post.self, to JSONDecoder().decode.