Chapters

Hide chapters

SwiftUI Apprentice

Third Edition · iOS 18 · Swift 5.9 · Xcode 16.2

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

19. Saving Files
Written by Caroline Begbie

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

You’ve set up most of your user interface, and it would be nice at this stage to have the card data persist between app sessions. You can choose between a number of different ways to save data.

You’ve already looked at UserDefaults and property list (plist) files in Section 1. These are more suitable for simple data structures, whereas, when you save your card, you’ll be saving images and sub-arrays of elements. While SwiftData could handle this, another way is to save the data to files using the JSON format. One advantage of JSON is that you can easily examine the file in a text editor and check that you’re saving everything correctly.

This chapter will cover saving JSON files to your app’s Documents folder by encoding and decoding the JSON representation of your cards.

The Starter Project

To assist you with saving UIImages to disk, the starter project contains methods in a UIImage extension to resize an image and to save, load and remove image files. These are in UIImageExtensions.swift.

If you’re continuing on from the previous chapter with your own code, make sure you copy this file into your project.

Instead of using previews, in this chapter you’ll build and run your app in Simulator so that you can inspect the Documents folder.

The Saved Data Format

When you save the data, each card will have a JSON file with a .card extension. This file will contain the list of elements that make up the card. You’ll save the images separately. The data store on disk will look like:

When to Save the Data

Skills you’ll learn in this section: when to save data; ScenePhase

Saving When the User Taps Done

➤ Open the starter project. In the Model folder, open Card.swift and create a new method in Card:

Using ScenePhase to Check Operational State

When you exit the app, surprisingly, the view does not perform onDisappear(_:), so the card won’t get saved. However, you can check what state your app is in through the environment.

JSON Files

Skills you’ll learn in this section: the JSON format

Codable

Skills you’ll learn in this section: Encodable; Decodable

Encoding

➤ In Team, create a new method:

Decoding

Reading the data back in is just as easy.

Encoding and Decoding Custom Types

Skills you’ll learn in this section: encoding; decoding; resolving Color values; compactMap(_:)

Encoding ImageElement

➤ Open CardElement.swift and take a look at ImageElement.

Decoding and Encoding the Card

➤ Open Card.swift and add a new extension with the list of properties to save:

Swift Dive: compactMap(_:)

compactMap(_:) returns an array with all the non-nil elements that match the closure. $0 represents each element.

SwiftUI Colors

Currently the card’s background color is a SwiftUI Color. This isn’t optimal, as a Color is an abstract value that is resolved only when it is displayed in a view, and depends on whether the device is using Dark or Light Mode.

Saving the Card

With most of the encoding and decoding in place, you can finally implement save().

Loading Cards

Skills you’ll learn in this section: file enumeration

File Enumeration

To list the cards, you’ll iterate through all the files with an extension of .card and load them into the cards array.

Creating new Cards

Without the default data, you’ll need some way of adding cards. You’ll create an Add button that you’ll enhance in the following chapter.

Challenge

This is a super-challenging challenge that will test your knowledge of the previous chapters too. You’re going to save text elements into the .card file. Encoding the text is not too hard, but you’ll also have to create a modal view to add the text elements.

Key Points

  • Saving data is the most important feature of an app. Almost all apps save some kind of data, and you should ensure that you save it reliably and consistently. Make it as flexible as you can, so you can add more features to your app later.
  • ScenePhase is useful to determine what state your app is in. Don’t try doing extensive operations when your app is inactive or in the background as the operating system can kill your app at any time if it needs the memory.
  • JSON format is a standard for transmitting data over the internet. It’s easy to read and, when you provide encoders and decoders, you can store almost anything in a JSON file.
  • Codable encompasses both decoding and encoding. You can extend this task and format your data any way you like.
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