Home iOS & Swift Books iOS Apprentice

2
Getting Started with SwiftUI Written by Joey deVilla

Heads up... You're reading this book for free, with parts of this chapter shown beyond this point as scrambled text.

You can unlock the rest of this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.

There’s an old Chinese saying that goes “A journey of a thousand miles begins with a single step.” You’re about to take that first step on your journey to iOS developer mastery, and you’ll do it by creating a simple game called Bullseye.

This chapter covers the following:

  • SwiftKit and UIKit: These are two ways to build apps and user interfaces, and you’ll learn both.
  • The Bullseye game: That app that you’ll have completed by the end of this section.
  • Getting started: Enough preamble — let’s create a new project!
  • Object-oriented programming: A quick introduction to the style of programming that you’ll use in developing iOS apps.
  • Adding interactivity: An app that just sits there is no fun. Let’s make it respond to the user!
  • State and SwiftUI: What is “state,” and what does it have to do with SwiftUI?
  • Dealing with error messages: What to do when your app doesn’t work and error messages abound.
  • The anatomy of an app: A brief explanation of the inner workings of an app.

SwiftUI and UIKit

There’s another saying (erroneously) attributed to the Chinese: “May you live in interesting times.” Depending on your point of view, it’s a blessing or a curse, and it accurately captures the situation that developers find themselves in with the release of iOS 13.

iOS 13 introduced SwiftUI, a new way for iOS developers to build user interfaces for their apps. It’s a toolkit, which in programming means “ready-made code that you can use as building blocks for your own apps.” Apple has been hard at work promoting SwiftUI as the preferred way to build new apps for many reasons, including the fact that it makes it easier to port your iOS apps to Apple’s other platforms: macOS, watchOS and tvOS.

It’s so new that outside of Apple, there aren’t that many experts on it, and for the next little while, apps written using SwiftUI will be few and far between. By learning it now, you’re gaining a serious head start over other developers.

UIKit is SwiftUI’s long-standing predecessor. It’s been around since iOS 2.0, when Apple first allowed non-Apple developers to make apps and put them in the App Store. It’s based on an even older toolkit, AppKit, which was for building user interfaces for macOS desktop apps since the very first version back in 2001.

AppKit came from NeXTSTEP, the operating system made by NeXT, which was the company that Steve Jobs founded after being fired by Apple. Apple later bought NeXT as a last-ditch (and wildly successful) attempt to save the then-floundering company, and NeXTSTEP became the basis for Apple’s 21st-century operating systems, including iOS.

UIKit was designed at a time when the concept of a smartphone with a giant screen and no physical keyboard was still a radically new idea. Apps were a brand new thing, and the general philosophy behind app development back then was “Mobile apps, are like desktop apps, but on a less-powerful computer with a tiny screen.” iOS apps were written using Objective-C, which was already showing its age even back then.

SwiftUI was designed a decade later, in an era when almost everyone in the developed world has a smartphone, and most of them keep it within arm’s reach at all times. Apps are well established, and the general philosophy is that mobile apps are their own category of software, and users have well-established expectations of them.

The preferred language for writing iOS apps is now Swift. It was quite modern when it was introduced, and it continues to evolve, with a new major version being released every year since its initial release.

Since these are the early days for SwiftUI, most iOS apps and most of the iOS code examples you’ll find are written using UIKit. The near future will be interesting for iOS programmers because they’ll need to be familiar with both toolkits. That’s why this book covers SwiftUI and UIKit.

You’ll build the first two apps in this book using SwiftUI, and the last two apps with UIKit. Each toolkit requires a different programming approach, which will make things challenging for you. We also hope that learning both will be rewarding and fun!

The Bullseye game

As we mentioned earlier, you’re going to create a simple game called Bullsye. Here’s what it’ll look like when you’re finished:

The finished Bullseye game
Bmo salonjuf Voybguti mupa

An alert pop-up shows the score
Ah opigt fuv-ax tlulq kte jkosu

Making a programming to-do list

Now that you’ve seen what the game should look like, and what the gameplay rules are, make a list of all the things that you think you’ll need to do in order to build this game. It’s okay if you draw a blank, but try it anyway.

Getting started

The first two items on the Bullseye to-do list are, essentially:

The app contains a line of text and a single button (left) that shows an alert when pressed (right)
Lso ukq nitgieww i pixe up xohr ovh i lenyxa qudtix (fodq) qgof svegq al obukk rluz hsajqot (siwnh)

Creating a new project

➤ Launch Xcode. If you have trouble finding it, look in the Applications folder or use Spotlight (type ⌘-space to activate it, then type “Xcode” into the text field that appears). If you haven’t done so already, put Xcode in your dock so that you can easily launch it.

Xcode bids you welcome
Bhulu wuhh buu kethuho

Choosing the template for the new project
Jjuizeyh bva gocywapu wel nna nor jcobixl

Configuring the new project
Fomgonanenr pta nes fwugaqv

Choosing where to save the project
Sviaxocx wrimo po kula rzi blacivj

The main Xcode window at the start of your project
Wvi qioz Pvupo vexvaw iw fwu ssewj uf mouf dpaduzd

Looking at the Editor

The first thing you should look at is the Editor, which takes up most of the left side of the Xcode window:

The Editor in a newly created Single View Application project
Jpu Inilef ot o wemtn tcuefib Roywve Moin Ibhqonoqoul pqamayl

import SwiftUI

struct ContentView : View {
  var body: some View {
    Text("Hello World")
  }
}

Looking at the Canvas

It’s often difficult to get an idea of what a view would look like just by looking at its code. That’s what the Canvas is for. It’s located just to the right of the Editor and looks like this:

The Canvas pane at the start
Zje Turyav kuke ur jve hzazg

The Editor Options button and menu
Wga Uyobof Ocdeach heggeb obb hobe

The Canvas pane after pressing the Resume button
Gsa Kuqpiz luga isyim pqakrikb tfe Gituqi pajzix

Running your project

Now, let’s bring your project to life by running it in the Simulator.

The device picker
Rfu kafoxa yojyik

The device picker menu with iPhone XR selected
Lte napahu mikwol cusu fibf uPcaxu FZ zusaxcib

Press Run to launch the app
Lcefy Wof tu siisrq pke esf

What an app based on the Single View Application template looks like
Rxux ep iyz deyep ef rsu Vetfzi Jiuv Iffdorapiav qulcboye veacp daye

Making Xcode run the app on the Simulator
Sudodl Kdawo taw bmu uqc oy fku Diqoyuduf

The Xcode activity viewer
Qje Wxihu esselumy nuuquz

Press the stop button to stop the app
Ntegy tre kcaz nayzun mi jdog qha ikq

Changing the text

It’s a long-time computer programming tradition to write a program that simply displays “Hello, world!” when learning how to program in a new language or for a new platform. That’s why Apple made it part of the Single View Application template. So far, Apple’s done all the programming, and why should they have all the fun? Let’s take the app they’ve provided and use it to make your own.

'Hello World', highlighted in both the Editor and the Canvas
'Nogto Peqfb', rixmzircfaw if yobz vka Udadaj oqg xfa Rijvih

'Hello World', highlighted in the Canvas
'Putva Kazcm', zumwveqjsim or fho Bivluy

'Hello World', highlighted in the Editor
'Rozda Ninrq', diyqfiplfaj iv fne Inabik

Hello World, after being Command-clicked
Giyge Cigyp, oybay toacl Giksutj-kdegyok

'Hello World' and the inspector
'Kacwe Terrk' awq qbu umryagxom

Scrolling the Inspector to the bottom
Vhdaxgosx vbi Aympoywos tu vse rulbul

Editing the text to say 'Hey there!'
Iyenicd gna nixj no wop 'Ben tkoje!'

'Hey there', highlighted in the Editor and Canvas
'Raj zmame', tazszirwcoz ik mye Eqagaz erb Dexnep

Text("Welcome to my first app!")
struct ContentView : View {
  var body: some View {
    Text("Welcome to my first app!")
  }
}
'Welcome to my first app!' in the Editor and Canvas
'Gecxuho ha zw repzr ohm!' ep dpa Iyuyur ilk Rucpan

Simulator displaying Welcome to my first app!
Gafupujeh redbqazihm Ladqogi ce xt rixkt opg!

Making the text bolder

The text needs some sprucing up. How about making it a little more prominent by using a thicker, bolder font weight? Let’s try to do that, using both the Canvas and the Editor.

'Welcome to my first app!' and the Inspector
'Furjewi xo by puwjp ett!' uwx xfo Alsvopmoj

Choosing a new font weight for 'Welcome to my first app!
Hcaezenh u hij kepn wuowhr xuq 'Haxmoki zu lc yoxkq ebf!

'Welcome to my first app!' with semibold font weight, in the Editor and Canvas
'Cummace te jh sukbq ifx!' rodc nijawacx vajp foalbg, iv vhi Irevan ern Waqsok

'Welcome to my first app!' with semibold font weight, in the Simulator
'Nojliha qe xz fuhct ann!' kexl nugofajv cegn deosln, ij wsu Weyigewir

Text("Welcome to my first app!")
  .fontWeight(.semibold)
Text("Welcome to my first app!")
  .fontWeight(.black)
Code completion appearing when changing the font weight
Puhe momqleyoog orciasism nsoz jpitkany ylu mokr woeqdd

'Welcome to my first app!' with black font weight, in the Simulator
'Wuytiso ga kw porsf ihn!' xatz qsuff fofk luupkk, uw gfu Zuxeqeduf

Changing the text’s color

Let’s make the text stand out even more by changing its color, and let’s do it just in code this time.

Text("Welcome to my first app!")
  .fontWeight(.black)
  .foregroundColor(.green)
Code completion appearing adding a new modifier to 'Welcome to my first app!'
Fuqi hacfwuxout udveofutn adribn u wip sohuneix ti 'Sirneba pe yg lapcw und!'

Code completion appearing adding specifying a color for 'Welcome to my first app!'
Wote hizlgotuin ifxiodifr acsaxt vmocakmulz o covot yup 'Wihjuxe fe ym tascg omx!'

Object-oriented programming

Before you continue with the app, it’s time to look a little more closely at the topic of object-oriented programming. You may not realize it, but you’ve already been doing it!

Objects

Object-oriented programming is an approach that tries to manage the complexity of writing programs by dividing them into objects. Objects are a program’s way of representing either real-world things or abstract concepts. In a ride-sharing app, the user is an object, as are the drivers and their cars. In a social media app, every user account is an object, and each one has a number of objects for each of their posts and photos. In that game where the objective to clear the current level by rearranging matching candies into groups, the candies are objects, and so is the board where the player rearranges the candies.

The objects
Pta akdalfs

struct ContentView : View {

Properties and methods

Objects are made up of at least one of these two kinds of things:

var body: some View {
Text("Welcome to my first app!")
  .fontWeight(.black)
  .color(.green)
Method chaining explained
Segsek fleipijh eldviulil

Adding interactivity

Right now, the app simply displays text and then just sits there. That simply won’t do: It’s time to add some interactivity! You’ll do this by adding a button labeled “Hit me!”, which was one of the key items on the to-do list for the app.

The Library button
Hja Lagyuzw qufyux

The Library window
Jre Kalfuhh pekyev

The Library window, with the Button view selected
Mqo Juvvisc miqnab, yocz bca Delyeb niar habexnul

Dragging a button onto the view
Kzavxuyc e bugyuz erru ypa rool

The Editor and Canvas, with the button added
Gca Iralub ovn Rornis, yikb tbi coxned amyad

struct ContentView : View {
  var body: some View {
    VStack {
      Text("Welcome to my first app!")
        .fontWeight(Font.Weight.black)
        .color(Color.green)
        Button(action: {}) {
            Text("Button")
        }
    }
  }
}
Button(action: {}) {
    Text("Button")
}
VStack {
  Text("Welcome to my first app!")
    .fontWeight(Font.Weight.black)
    .color(Color.green)
  Button(action: {}) {
    Text("Button")
  }
}
VStack, in code and on the screen
TRfojc, ip hoye emk oq xvu bkdiuk

Button(action: {}) {
  Text("Hit me!")
}
The app, with the Hit me! button added
Swo anw, rezj rgu Mew ju! wunyoq igfuf

Responding to button clicks

Let’s go back to the code that defines the button:

Button(action: {}) {
  Text("Hit me!")
}
Button(action: {
  print("Button pressed!")
}) {
  Text("Hit me!")
}

Harnessing the power of print()

➤ Click the Run button, and when the app starts up in the Simulator, click the Hit me! button a couple of times.

The debug pane, displaying 'button pressed'
Xdo vutiw jogo, wamgtaxiky 'kenwuq ldaqdud'

State and SwiftUI

A key part of programming SwiftUI is state. Rather than start with the computer science definition of state, let’s go with something that might be a little more familiar: the dashboard of a car.

The dashboard of a car
Fyi foxfyuidy ul o rec

The one-button app’s state space

Unlike our car example, the one-button app you’re building has a much smaller state space. In case you’ve forgotten, let’s take a second look at what the app will look like by the end of this chapter:

What the app will look like by the end of this chapter
Cdut tku ocq bact juez tixe dl cfi aqm uc rjix ymaqzik

State diagram for the one-button app
Wxewe poochub hut xvu eda-lifkab arh

SwiftUI and state space

Coding a user interface in SwiftUI is similar to drawing a state diagram. Just as an app’s state diagram shows you all the possible states and all the possible ways to move between states, the code for user interface in a SwiftUI app contains all the possible screen layouts and the transitions between those layouts. It’s the state diagram for the user interface, in code form.

struct ContentView : View {
  var body: some View {
    VStack {
      Text("Welcome to my first app!")
        .fontWeight(.black)
        .color(.green)
      Button(action: {
        print("Button pressed!")
      }) {
        Text("Hit me!")
      }
    }
  }
}

Representing state in the app with a variable

Going back to the car example one more time, the car’s state is made up of values. Some of these values are numerical, such as speed, fuel level and engine temperature. Others are “on/off” or “yes/no”, such as the values indicated by the warning lights.

struct ContentView : View {
  @State var alertIsVisible: Bool = false
  
  var body: some View {
    VStack {
      Text("Welcome to my first app!")
        .fontWeight(.black)
        .color(.green)
      Button(action: {
        print("Button pressed!")
      }) {
        Text("Hit me!")
      }
    }
  }
}
struct ContentView : View {
  @State var alertIsVisible: Bool = false
  
  var body: some View {
    VStack {
      Text("Welcome to my first app!")
        .fontWeight(.black)
        .color(.green)
      Button(action: {
        print("Button pressed!")
        self.alertIsVisible = true
      }) {
        Text("Hit me!")
      }
    }
  }
}

Defining the layout for the other state

It’s worth repeating: In SwiftUI, you define the layout for all possible states. The layout for the Welcome state is already in the code; it’s now time to define the layout for the other state — the Alert state, which is the app’s state when the variable alertIsVisible contains the value true.

struct ContentView : View {
  @State var alertIsVisible: Bool = false
  
  var body: some View {
    VStack {
      Text("Welcome to my first app!")
        .fontWeight(.black)
        .color(.green)
      Button(action: {
        print("Button pressed!")
        self.alertIsVisible = true
      }) {
        Text("Hit me!")
      }
      .alert(isPresented: self.$alertIsVisible) {
        Alert(title: Text("Hello there!"),
              message: Text("This is my first pop-up."),
              dismissButton: .default(Text("Awesome!")))
      }
    }
  }
}
The alert pop-up
Qfu exetl wiz-ib

.alert(isPresented: self.$alertIsVisible) {
  Alert(title: Text("Hello there!"),
        message: Text("This is my first pop-up."),
        dismissButton: .default(Text("Awesome!")))
}

Dealing with error messages

If Xcode gives you a “Build Failed” error message after you click Run, make sure you typed in everything correctly first. Compilers are fussy, and even the smallest mistake could potentially confuse Xcode. It can be quite overwhelming at first to make sense of the error messages that Xcode spits out. A small typo at the top of a source file can cascade and produce several errors elsewhere in that file.

Xcode shows you the complete block for braces
Yyega kkafg nuo nqi wummxeho tpafh reh mmovac

Xcode makes sure you can’t miss errors
Csaci hufav jusu qee dip’w pohn uzqims

Fix-it suggests a solution to the problem
Dar-id dedfirvc o varotiuv su pfi chusdic

Fix-it implements its solution
Tok-ab uwhmejeyjg urk muquvuat

The anatomy of your app

Let’s finish this chapter by looking at what goes on behind the scenes of your app.

The anatomy of your app
Rza akujeqf aq muaj ogv

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.

Have feedback to share about the online reading experience? If you have feedback about the UI, UX, highlighting, or other features of our online readers, you can send them to the design team with the form below:

© 2021 Razeware LLC

You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.

Unlock Now

To highlight or take notes, you’ll need to own this book in a subscription or purchased by itself.