Chapters

Hide chapters

macOS Apprentice

First Edition · macOS 13 · Swift 5.7 · Xcode 14.2

Section II: Building With SwiftUI

Section 2: 6 chapters
Show chapters Hide chapters

Section III: Building With AppKit

Section 3: 6 chapters
Show chapters Hide chapters

4. Running Swift in a Playground
Written by Sarah Reichelt

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

In the previous chapters, you used basic Swift types and collections. You learned how to loop, evaluate conditions and write functions. You ran Swift in Terminal, and you used Xcode to create a command line tool.

In this chapter, you’ll take what you know and combine it to make your own custom data types. You’ll run this code in a playground, which is a way of running Swift interactively in Xcode.

If you’re already familiar with classes, structures, enumerations, inheritance and protocols, then you can skip ahead to the next chapter.

Running a Playground

Open Xcode and close the “Welcome to Xcode” window, if it appears. Use the menu bar to choose File ▸ New ▸ Playground… and select macOS and Blank from the template chooser. Name your playground CustomTypes.playground and save it in your Developer folder or wherever you prefer.

Your playground opens looking like this:

A Swift Playground
A Swift Playground

There are three main sections in this window:

  1. The navigator: Playgrounds allow you to have multiple pages and to bring in external code files or assets. You’ll see them all listed here.
  2. The code editor where you’ll type all your Swift.
  3. The results panel that shows the result of each line of code.

At the left side of the code, there’s a blue column with line numbers and after the last line, a blue play button. Click it to run the default code:

Running the Playground
Running the Playground

“Hello, playground” appears in the results panel as the playground executes that line. Mouse over it to see two new controls. The box on the left is a toggle that shows or hides the result inline with the code. The eye icon opens a larger popup displaying the value.

The play button in the line numbers gutter is what you’ll use use to run the playground whenever you make a change.

Classes

So far, every type of data you’ve used has been one of Swift’s built-in types like String or Double. But in the real world, you’ll need more complicated data types that combine these in various ways.

// 1
class StockItem {
  // 2
  let name: String
  var numberInStock: Int
}
// 1
init(name: String, numberInStock: Int) {
  // 2
  self.name = name
  self.numberInStock = numberInStock
}

Creating a Class Instance

To create your first instance of the class, add this outside the class declaration:

var bananas = StockItem(name: "banana", numberInStock: 12)
Creating an instance of a class.
Sxaetotm uc azblolxi al u rvitt.

// 1
bananas.name
// 2
bananas.numberInStock += 1
// 3
bananas
Accessing an instance's properties.
Ixdeqvegk ad ejkyedqu'q dludixhaiy.

Adding Methods

You already edited the numberInStock property manually, but that doesn’t allow for any error checking, so now you’ll add methods to do this.

// 1
func buy(number: Int) {
  // 2
  numberInStock += number
}

// 3
func sell(number: Int) {
  // 4
  if number > numberInStock {
    numberInStock = 0
  } else {
    numberInStock -= number
  }
}
// 1
bananas.buy(number: 4)
bananas.numberInStock

// 2
bananas.sell(number: 2)
bananas.numberInStock

// 3
bananas.sell(number: 1000)
bananas.numberInStock
Calling class methods.
Fahxogj vhulr wakcebf.

Reference Types

It would be a very boring shop that sold nothing but bananas, so create some new instances:

let apples = StockItem(name: "apple", numberInStock: 0)
let oranges = StockItem(name: "orange", numberInStock: 24)
apples.buy(number: 16)
oranges.sell(number: 3)
Editing a constant class instance.
Oqujunz e fejsdixj qvufs exmzorfo.

apples.name = "Golden Delicious"
Trying to edit a constant property.
Xlseth nu iciq a zofhbupr kduzuncs.

Structures

You’re going to use another playground page for this, so go to File ▸ New ▸ Playground Page or press Option-Command-N to add a page.

Adding a page to the playground.
Ewjexq i feri je yvi szajkbaikl.

// 1
struct StockItem {
  // 2
  let name: String
  var numberInStock: Int
}
// 3
var peaches = StockItem(name: "peach", numberInStock: 6)
Initializing a structure instance.
Ilavaatucomx i lpnixyafa ejqrinti.

Adding Structure Methods

Add a blank line after the structure’s properties and insert these methods:

func buy(number: Int) {
  numberInStock += number
}

func sell(number: Int) {
  if number > numberInStock {
    numberInStock = 0
  } else {
    numberInStock -= number
  }
}
Structure method errors
Pgveqkinu jaszix afligz

peaches.name
peaches.numberInStock += 1

peaches.buy(number: 4)
peaches.numberInStock

peaches.sell(number: 2)
peaches.numberInStock

peaches.sell(number: 1000)
peaches.numberInStock
Structure operations
Slduclivi aniyovoikm

Value Types

Try adding this code:

let limes = StockItem(name: "lime", numberInStock: 3)
limes.buy(number: 9)
Editing a constant structure instance.
Urugewc i bendjasw mtxuxyiwu uthrotxe.

Enumerations

An enumeration, or enum, is a type where you give it a set of predefined options. Each instance must be one of those options. Imagine you’re implementing a login system. What are the possible states for a user?

// 1
enum LoginState {
  // 2
  case loggedIn
  case loggedOut
  case banned
  case admin
}
var userStatus = LoginState.loggedOut
userStatus = .admin
Declaring and using an enumeration.
Pibvazujq ulh olann og oyasudulaun.

Adding Enumeration Methods

Maybe you’d like to show a message to the user depending on the login status. Add this method before the closing curly brace in LoginState:

// 1
func displayMessage() -> String {
  // 2
  switch self {

  }
}
switch self {

case .loggedIn:
  return "Welcome, user"
case .loggedOut:
  return "Log in to access this site."
case .banned:
  return "*** BANNED ***"
case .admin:
 return "Welcome, mighty administrator!"
}
var displayMessage: String {
userStatus.displayMessage

Inheritance

You may have heard of Object-Oriented Programming or OOP. This is a system of programming that uses classes and subclasses. A subclass is a class that inherits from a parent class.

// 1
class SoftDrinkItem: StockItem {
  // 2
  var isFizzy: Bool

  // 3
  init(name: String, numberInStock: Int, isFizzy: Bool) {
    // 4
    self.isFizzy = isFizzy
    // 5
    super.init(name: name, numberInStock: numberInStock)
  }
}

Initializing a Subclass Instance

This class has inherited everything from its parent, so you can initialize it and use the parent’s methods like this:

// 1
let mineralWater = SoftDrinkItem(
  name: "Mineral water",
  numberInStock: 12,
  isFizzy: false)

// 2
mineralWater.sell(number: 3)
Defining and using a subclass.
Yopupudw inq iliph e jovdpiwg.

mineralWater is SoftDrinkItem
mineralWater is StockItem
var stocks = [bananas, apples, mineralWater]
Class array
Nkotx aqnus

Overriding Parent Methods

Your fruit seller now tells you that they always buy soft drinks in boxes of 12, so this class needs a custom buy(number:) that adds 12 to numberInStock for every purchase. SoftDrinkItem needs to override its parent’s buy(number:) and supply its own.

// 1
override func buy(number: Int) {
  // 2
  numberInStock += number * 12
}
mineralWater.numberInStock
mineralWater.buy(number: 2)
mineralWater.numberInStock
Using an override method.
Usicb in uxopzora yursey.

Protocols

One alternative to Object-Oriented Programming is Protocol-Oriented Programming or POP. With POP, you don’t have types inheriting from parent types, you have them conforming to a protocol. So what is a protocol?

// 1
protocol StockItemProtocol {
  // 2
  var name: String { get }
  // 3
  var numberInStock: Int { get set }

  // 4
  mutating func buy(number: Int)
  mutating func sell(number: Int)
}

Conforming to a Protocol

Now you’ll implement a structure conforming to the protocol.

struct StockItem: StockItemProtocol {

}
numberInStock += number
 numberInStock -= number
var mangos = StockItem(name: "mango", numberInStock: 5)

mangos.buy(number: 3)
mangos.sell(number: 1)
mangos.numberInStock
struct SoftDrinkItem: StockItemProtocol {
  var name: String
  var numberInStock: Int
  var isFizzy: Bool

  mutating func buy(number: Int) {
    numberInStock += number * 12
  }

  mutating func sell(number: Int) {
    numberInStock -= number
  }
}
var lemonades = SoftDrinkItem(
  name: "lemonade",
  numberInStock: 24,
  isFizzy: true)
var stocks: [StockItemProtocol] = [mangos, lemonades]

Extending Your Protocol

When you dealt with inheritance, you only had to write a common method once. In protocols, it looks like you have to write every method for every conforming type.

// 1
extension StockItemProtocol {
  // 2
  mutating func buy(number: Int) {
    numberInStock += number
  }

  mutating func sell(number: Int) {
    numberInStock -= number
  }
}
mangos.numberInStock = 0
mangos.buy(number: 2)
mangos.sell(number: 1)
mangos.numberInStock

lemonades.numberInStock = 0
lemonades.buy(number: 1)
lemonades.sell(number: 1)
lemonades.numberInStock
Protocol methods
Nfivisac gikjavh

What to Use?

You’ve now seen three different custom types in action: classes, structures and enumerations.

Key Points

  • Playgrounds are a useful tool for learning Swift and testing your code outside a full app.
  • There are three main custom type formats: classes, structures and enumerations.
  • Classes can inherit from a parent class to share common properties and methods.
  • Both classes and structures can conform to protocols, which are contracts setting out what properties and methods a conforming type must have.
  • Enumerations allow for predefined sets of options.

Where to Go From Here

This is the end of your brief introduction to Swift and how you can run it on your Mac. There’s a lot of Swift that you haven’t seen yet, but you know enough to get started building apps for your Mac.

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.
© 2024 Kodeco Inc.

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 Kodeco Personal Plan.

Unlock now