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

15. Structures, Classes & Protocols
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

It’s time to build the data model for your app so you have some data to show on your app’s views.

The four functions that data models need are frequently referred to as CRUD. That’s Create, Read, Update, Delete. The easiest of these is generally Read, so in this chapter, you’ll first create the data store, then build views that read the store and show the data. You’ll then learn how to Update the data and store it and, finally, how to Delete it. That will leave Create, and you’ll learn how to add new cards with photos and text in a later chapter.

Starter project changes

There are a few differences between the challenge project from the last chapter and the starter project of this chapter:

  • Operators.swift: contains a new operator to multiply a CGSize by a scalar.
  • Preview Assets.xcassets: contains three cute hedgehogs from http://pexels.com.
  • PreviewData.swift: contains sample data that you’ll use until you’re able to create and save data.
  • TextExtensions.swift: contains a new view modifier to scale text.

➤ If you are continuing with your own project, be sure to copy these files into your project.

Data structure

Take another look at the back of the napkin sketch:

Gutw ot fbo yakbal tlutch
Qigh ol kpi solbad ppupgc

Sodo rmvimjoxa
Sumi bsnoqkuzi

Value and reference types

Skills you’ll learn in this section: differences between value and reference types

Sejeo asf zolazulwe xkdep
Vidou ovl zuteraffa ymyar

Swift Dive: Structure vs class

Skills you’ll learn in this section: how to use structures and classes

Creating the card store

Skills you’ll learn in this section: when to use classes and structures

Class inheritance

Skills you’ll learn in this section: class inheritance; composition vs inheritance

Composition vs Inheritance

With inheritance, you have tightly coupled objects. Any subclass of a CardElement class automatically has a transform property whether you want one or not.

Fokkeyufoon
Fuxrowedeal

Protocols

Skills you’ll learn in this section: create protocol; conform structures to protocol; protocol method

Creating a default protocol method

Part of a protocol blueprint might be requiring the conforming type to implement a method. For example, this protocol requires all types that conform to it to implement find():

The preview data

Skills you’ll learn in this section: using preview data

Listing the cards

Skills you’ll learn in this section: didSet property observer; mutability

Jke xoqg mpalnjoosy
Hru zovh fqawyheidq

Choosing a card

When you tap a card, you toggle viewState.showAllCards, and the parent view, CardsView, should show SingleCardView using the data for the selected card. Rather than pass bindings around for the selected card, you’ll hold it in ViewState.

The didSet observer

Of course, when you are listing all cards and no card is currently selected, viewState.selectedCard should be nil. You control display of this list with viewState.showAllCards. You could go and hunt down all the places that you set showAllCards true, but you can use the property observer didSet instead.

Displaying the single card

You can now pass the selected card to the single card view.

O behmogj ozr
U madsemf ubh

Convenience initializer

➤ Open SingleCardView.swift.

Weqt bohguyaozrzc ekavuajewoy
Saxt huwfufiixlgw ukayiayeyaq

Adding elements to the card detail view

With the card passed to CardDetailView, you can now show the card’s elements.

Yurp moqjgfeuks bviy cji jhaxeim fora
Luyk liqhtniikx nqep bda lpajuod toxe

Creating the card element view

➤ In the Single Card Views group, create a new SwiftUI View file named CardElementView.swift. This view will show a single card element.

Wvo qarx axeterj peac
Kgo susj abexiqw xoap

Showing the card elements

➤ Open CardDetailView.swift, locate var content and add this after .edgesIgnoringSafeArea(.all):

Qba vijd uxixiwxl
Tbe muzl ofuxokgx

Understanding @State and @Binding property wrappers

Skills you’ll learn in this section: @State; binding; generics

MatmXobiecFiel xodyoseguuxd
XejyLexeajReuv kupsihaxuobv

Swift Dive: A very brief introduction to generics

Swift is a strongly typed language, which means that Swift has to understand the exact type of everything you declare. Binding has a generic type parameter <Value>. A generic type doesn’t actually exist except as a placeholder. When you declare a binding, you associate the current type of binding that you are using. You replace the generic term <Value> with your type, as in the above example Binding<Card>.

Binding transform data

Now that you’ve seen how generics work when composing a binding declaration, you’ll be able to extract a binding transform from the immutable card element in CardDetailView. You’ll pass this transform to resizableView(), and ResizableView will connect to this binding instead of updating its own internal state transform property.

Updating CardDetailView preview

The live preview in CardDetailView will no longer allow you to move or resize elements.

Ujafayjk im mnaig muhbesw camebiiw
Ehediwzz ef lwiuv xihyowd yalojuom

Ojqefatz xsu fibk
Oqqiguty tru pilv

Deletion

Skills you’ll learn in this section: context menu; deletion; remove from array

Yipule mets uzozuyn
Guraso nakc egibumr

Challenge

Challenge: Delete a card

You learned how to delete a card element and remove it from the card elements array. In this challenge you’ll add a context menu so that you can delete a card.

Key points

  • Use value types in your app almost exclusively. However, use a reference type for persistent stored data. When you create a value type, you are always copying the data. Your stored data should be in one central place in your app, so you should not copy it. Occasionally, Apple’s APIs will require you to use a class, so you have no choice.
  • When designing a data model, make it as flexible as possible, allowing for new features in future app releases.
  • Use protocols to describe data behavior. An alternative approach to what you did in this chapter would be to require that all resizable Views have a transform property. You could create a Transformable protocol with a transform requirement. Any resizable view must conform to this protocol.
  • You had a brief introduction to generics in this chapter. Generics are pervasive throughout Apple’s APIs and are part of why Swift is so flexible, even though it is strongly typed. Keep an eye out for where Apple uses generics so that you can gradually get familiar with them.
  • When designing an app, consider how you’ll implement CRUD. In this chapter, you implemented Read, Update and Delete. Adding new data is always more difficult as you generally need a special button and, possibly, a special view. You’ll add photos from your photos collection to your cards later on.

Where to go from here?

You covered a lot of Swift theory in this chapter. The book Swift Apprentice https://bit.ly/3eFtqQa by our team contains more information about how and when to use value and reference types. It also covers generics and protocol oriented programming.

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