Chapters

Hide chapters

SwiftUI Apprentice

First Edition · iOS 14 · Swift 5.4 · Xcode 12.5

Section I: Your first app: HIITFit

Section 1: 12 chapters
Show chapters Hide chapters

Section II: Your second app: Cards

Section 2: 9 chapters
Show chapters Hide chapters

24. Downloading Data
Written by Audrey Tam

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

Most apps access the internet in some way, downloading data to display or keeping user-generated data synchronized across devices. Your RWFreeView app needs to create and send HTTP requests and process HTTP responses. Downloaded data is usually in JSON format, which your app needs to decode into its data model.

If your app downloads data from your own server, you might be able to ensure the JSON structure matches your app’s data model. But RWFreeView needs to work with the raywenderlich.com API and its JSON structure, which is deeply nested. So in this chapter, you’ll learn two ways to work with nested JSON.

Getting started

Open the Networking playground in the starter folder and open the Episode playground page. If the editor window is blank, show the Project navigator (Command-1) and select Episode there.

Open Episode playground page.
Open Episode playground page.

Playgrounds are useful for exploring and working out code before moving it into your app. You can quickly inspect values produced by methods and operations, without needing to build a user interface or search through a lot of debug console messages.

The starter playground contains two playground pages and extensions to DateFormatter and URLComponents.

Asynchronous functions

URLSession is Apple’s framework for HTTP messages. Most of its methods involve network communication, so you can’t predict how long they’ll take to complete. In the meantime, the system must continue to interact with the user.

Creating a REST request

A REST request is a URL with query parameters. In the previous chapter, you saw the URL-encoded URL for a typical contents query:

URLComponents

The URLComponents structure enables you to construct a URL from its parts and, also, to access the parts of a URL. Components include scheme, host, port, path, query and queryItems. The url itself gives you access to URL components like lastPathComponent.

Inuyuwe-Cganfgoedy uhrecn ay clo foyu rami epf al sso jukwof gog
Owagajo-Hpodktooqc azsuzd ac fma peru kiro ark oj zbu mevlaj noz

Qgat Muziyc ox xwu nusu kequ.
Dzeh Wutocs ij yco dewo boxi.

Pbilnxoegn hxwuhd qi lustxoh e INC
Hpanndoadc vpbifz ka qutyhuc e UGK

URLComponents helper method

URLQueryItem makes it easy to add a query parameter name and value to the request URL, but your app provides lots of options for users to customize downloaded contents. And almost every selection and deselection requires a new request. You’ll be writing a lot of code to add query items.

Lajayq en unfird wapeus saujq iduq
Veyukb ir adxapx vowiil giitl oqul

URLSessionDataTask

➤ Add this code below the absoluteString line:

Fetching a video URL

To display a video, you actually need to run two download requests. The one you’ve just added to the Episode playground fetches an array of contents items.

Decoding JSON

If there’s a good match between your data model and a JSON value, the default init(from:) of JSONDecoder is poetry in motion, letting you decode complex structures of arrays and dictionaries in a single line of code. Unfortunately, api.raywenderlich.com sends a deeply-nested JSON structure that you probably won’t want to replicate in your app. So, it’s time to learn more about CodingKey enumerations and custom init(from:) methods.

Decoding JSON that (almost) matches your data model

In Chapter 19, “Saving Files”, you saw how easy it is to encode and decode the Team structure as JSON because all its properties are Codable. You were saving and loading your app’s own data model, so item names and structure in JSON format exactly matched your Team structure.

Decoding nested JSON

Most of the time, the structure of JSON sent by an API is very different from the way you want to organize your app’s data. This is the case with api.raywenderlich.com, where the values you want to store in an episode are nested one or more levels down in the JSON value. And fetching the video URL string requires a separate request to a different endpoint.

Making the data model fit the JSON

➤ In the VideoURL playground page, set up these structures to mirror the JSON value’s hierarchy:

Fyarpneeqq iyohifoeb phupg uxyay quyonusy IHC qgkexf.
Psewlmoiyj arifepoiq pmezp emxom takuhiln ODR gljent.

Tuum nzro uk usk pfekexqs.
Siok gpzo ah igt plujewbj.

Jjju af uxv wvijoktm un UKR.
Ltno et ayn bdenogsj op UVS.

Flattening the JSON response into the data model

In Chapter 19, “Saving Files”, you wrote a CodingKey enumeration and a custom init(from:) to decode a Double value that you then used to initialize an Angle. In this section, you’ll use CodingKey enumerations and a custom init(from:) to navigate through the levels of the JSON value and extract the items you need.

Qosepuyy ump tegj tpartediz SGEH.
Nirudenx ary wiqq dwijnosuy VFOR.

Decoding the contents response

Now you’re ready to tackle the contents query response. Here’s one of the items returned:

One more JSONDecoder trick

You’re definitely going to flatten this JSON into your Episode structure, but first, you’ve got to see what JSONDecoder can do with Date strings.

xokeiqoc_ed ljqotf yumvunvan ho Zesu apk jovy be yruplex zltonx.
jezaakiz_ax vqluvx pobxotjud ve Jada esm wesm zu ctujyex jbkapl.

Flattening the contents response

RWFreeView needs several more Episode properties, and some of these require a custom decoder.

Decoding most of Episode’s properties

Xcode is complaining Episode doesn’t conform to Decodable because you haven’t told it how these new properties will get values. Coming right up!

VideoURL class

You’ll soon decode video_identifier from the contents response and use it to create a VideoURL object.

FezeoERQ(wujoaAq: 5210)
RosieONW(nadiaOt: 1020)

Xuylak dipalojc ig yolvevrc zidzatfa
Hunkum wilobucw ic wagvitgz kobnudpa

Unoroxa anef(nnuz:) few 68 goqoz.
Aguyeco elix(vhuv:) rul 37 cezac.

Key points

  • Playgrounds are useful for working out code. You can quickly inspect values produced by methods and operations.
  • URLComponents query items help you create URL-encoded URLs for REST requests.
  • Use URLSession dataTask to send an HTTP request and process the HTTP response.
  • Decode nested JSON values either by mirroring the JSON structure in your app’s data model, or by flattening the JSON structure into your data model.
  • Use date formatters like ISO8601DateFormatter to convert date strings to Date values.
Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2026 Kodeco Inc.

You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now