Chapters

Hide chapters

Swift Apprentice: Fundamentals

First Edition · iOS 16 · Swift 5.7 · Xcode 14.2

Section III: Building Your Own Types

Section 3: 9 chapters
Show chapters Hide chapters

2. Types & Operations
Written by Matt Galloway

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

Now that you know how to perform basic operations and manipulate data using these operations, it’s time to learn more about types. Formally, a type describes a set of values and the operations you can perform on them. In this chapter, you’ll learn about handling different types, including strings that allow you to represent text. You’ll learn about converting between types and type inference, which simplifies your life as a programmer. Finally, you’ll learn about tuple types, which allow you to group values of any type together.

Type Conversion

Sometimes you’ll have data in one format and need to convert it to another. The naïve way to attempt this would be like so:

var integer: Int = 100
var decimal: Double = 12.5
integer = decimal

Swift will complain if you try to do this and spit out an error on the third line:

Cannot assign value of type 'Double' to type 'Int'

Some programming languages aren’t as strict and will perform conversions like this silently. Experience shows this kind of silent, automatic conversion is a source of software bugs and often hurts performance. Swift disallows you from assigning a value of one type to another and avoids these issues.

Remember, computers rely on us programmers to tell them what to do. In Swift, that includes being explicit about type conversions. If you want the conversion to happen, you have to say so!

Instead of simply assigning, you need to say that you want to convert the type explicitly. You do it like so:

integer = Int(decimal)

The assignment on the third line now tells Swift unequivocally that you want to convert from the original type, Double, to the new type, Int.

Note: In this case, assigning the decimal value to the integer results in a loss of precision: The integer variable ends up with the value 12 instead of 12.5. This danger of loss is why it’s important to be explicit. Swift wants to ensure you know what you’re doing and that you may lose data by performing the type conversion.

Operators With Mixed Types

So far, you’ve only seen operators acting independently on integers or doubles. But what if you have an integer that you want to multiply by a double?

let hourlyRate: Double = 19.5
let hoursWorked: Int = 10
let totalCost: Double = hourlyRate * hoursWorked
let totalCost: Double = hourlyRate * Double(hoursWorked)

Type Inference

Every variable or constant you’ve seen in this book so far includes a type annotation. You may be asking yourself why you need to bother writing the : Int and : Double since the right-hand side of the assignment is already an Int or a Double. It’s redundant, to be sure; your crazy-clever brain can see this without too much work.

let typeInferredInt = 42

let typeInferredDouble = 3.14159

let wantADouble = 3
let actuallyDouble = Double(3)
let actuallyDouble: Double = 3
let actuallyDouble = 3 as Double

Mini-Exercises

  1. Create a constant called age1 and set it equal to 42. Create a constant called age2 and set it equal to 21. Check using Option-click that the type for both has been inferred correctly as Int.
  2. Create a constant called avg1 and set it equal to the average of age1 and age2 using the naïve operation (age1 + age2) / 2. Use Option-click to check the type and check the result of avg1. Why is it wrong?
  3. Correct the mistake in the above exercise by converting age1 and age2 to type Double in the formula. Use Option-click to check the type and check the result of avg1. Why is it now correct?

Strings

Numbers are essential in programming, but they aren’t the only type of data you need to work within your apps. Text is also an extremely common data type used to represent things like people’s names, addresses, or even the words of a book. All of these are examples of text that an app might need to handle.

How Computers Represent Strings

Computers think of strings as a collection of individual characters. In Chapter 1, “Expressions, Variables & Constants”, you learned that numbers are the language of CPUs, and all code, in whatever programming language, can be reduced to raw numbers. Strings are no different!

Unicode

In isolation, a computer can choose whatever character set mapping it likes. If the computer wants the letter a to equal the number 10, then so be it. But when computers start talking to each other, they need to use a common character set.

z a m i 21 93 327 077

w o f é 62 17 584 360

12153 72383 12910 73092

💩 😀 886304 392793

Strings in Swift

Like any reasonable programming language, Swift can work directly with characters and strings. It does so through the data types Character and String. In this section, you’ll learn about these data types and how to work with them.

Characters and Strings

The Character data type can store a single character. For example:

let characterA: Character = "a"
let characterDog: Character = "🐶"
let stringDog: String = "Dog"
let stringDog = "Dog" // Inferred to be of type String

Concatenation

You can do much more than create simple strings. Sometimes you need to manipulate a string, and one common way to do so is to combine it with another string.

var message = "Hello" + " my name is "
let name = "Matt"
message += name // "Hello my name is Matt"
let exclamationMark: Character = "!"
message += String(exclamationMark) // "Hello my name is Matt!"

Interpolation

You can also build up a string by using interpolation, which is a special Swift syntax that lets you build a string in a way that’s easy to read:

message = "Hello my name is \(name)!" // "Hello my name is Matt!"
let oneThird = 1.0 / 3.0
let oneThirdLongString = "One third is \(oneThird) as a decimal."

Multi-line Strings

Swift has a neat way to express strings that contain multiple lines. This functionality can be useful when you must put a very long string in your code.

let bigString = """
  You can have a string
  that contains multiple
  lines
  by
  doing this.
  """
print(bigString)
You can have a string
that contains multiple
lines
by
doing this.

Mini-Exercises

  1. Create a string constant called firstName and initialize it to your first name. Also, create a string constant called lastName and initialize it to your last name.
  2. Create a string constant called fullName by adding the firstName and lastName constants together, separated by a space.
  3. Using interpolation, create a string constant called myDetails that uses the fullName constant to create a string introducing yourself. For example, my string would read: "Hello, my name is Matt Galloway.".

Tuples

Sometimes data comes in pairs or triplets. An example is a pair of (x, y) coordinates on a 2D grid. Similarly, a set of coordinates on a 3D grid is comprised of an x-value, a y-value and a z-value. In Swift, you can represent such related data in a straightforward way by using a tuple.

let coordinates: (Int, Int) = (2, 3)
let coordinates = (2, 3)
let coordinatesDoubles = (2.1, 3.5)
// Inferred to be of type (Double, Double)
let coordinatesMixed = (2.1, 3)
// Inferred to be of type (Double, Int)
let x1 = coordinates.0
let y1 = coordinates.1
let coordinatesNamed = (x: 2, y: 3)
// Inferred to be of type (x: Int, y: Int)
let x2 = coordinatesNamed.x
let y2 = coordinatesNamed.y
let coordinates3D = (x: 2, y: 3, z: 1)
let (x3, y3, z3) = coordinates3D
let coordinates3D = (x: 2, y: 3, z: 1)
let x3 = coordinates3D.x
let y3 = coordinates3D.y
let z3 = coordinates3D.z
let (x4, y4, _) = coordinates3D

Mini-Exercises

A Whole Lot of Number Types

You’ve been using Int to represent whole numbers. An Int is represented with 64 bits on most modern hardware and with 32 bits on older or more resource-constrained systems. Swift provides many more number types that use different amounts of storage. For whole numbers, you can use the explicit signed types Int8, Int16, Int32, Int64. These types consume 1, 2, 4, and 8 bytes of storage, respectively. Each of these types use 1 bit to represent the sign.

Wjru Alv89 -8000711711450576191 0459864156946693918 5 Qumuzof Vuvuo Yaguguf Qoboo Xlovowa voxu IOrh24 2 44610233979301321867 5 Enr96 -1029451396 9323668089 2 AOgg48 1 2161978495 1 Itc93 -01796 04862 6 EApn96 0 64988 8 Eww9 -523 622 0 UAll8 8 947 6

Cxmu Wmuug 2.944422A-08 9.047603U+84 3 miximd 4 Kebiber Siveo Woyovoj Gukoi Gsemumead Prewexe heki Zoubve 5.248409i-325 9.065759E+873 17 jonitd 2

let a: Int16 = 12
let b: UInt8 = 255
let c: Int32 = -100000

let answer = Int(a) + Int(b) + Int(c)  // answer is an Int

Type Aliases

A useful feature of Swift is being able to create your own type which is an alias of another type. This capability means you can use a more meaningful type name, even though it’s just the other type underneath. This is known as a type alias.

typealias Animal = String
let myPet: Animal = "Dog"
typealias Coordinates = (Int, Int)
let xy: Coordinates = (2, 4)

A Peek Behind the Curtains: Protocols

Even though there are a dozen different numeric types, they are easy to understand and use because they all roughly support the same operations. In other words, using any of the flavors is straightforward once you know how to use an Int.

Kekoran (Nzoqusej) WuparlIjkojew (Dmomunuy) Uqt7, Ozh50, Uns20, ... AzbijqijIqxohec (Thehajiv) HuthalEfyereq (Zvarecif) RehxayFehoniy (Gxugobam) OOmv6, AOxm62, EOxz31, ...

Challenges

Before moving on, here are some challenges to test your knowledge of types and operations. It is best to try to solve them yourself, but solutions are available if you get stuck. These came with the download or are available at the printed book’s source code link listed in the introduction.

Challenge 1: Coordinates

Create a constant called coordinates and assign a tuple containing two and three to it.

Challenge 2: Named Coordinate

Create a constant called namedCoordinate with a row and column component.

Challenge 3: Which Are Valid?

Which of the following are valid statements?

let character: Character = "Dog"
let character: Character = "🐶"
let string: String = "Dog"
let string: String = "🐶"

Challenge 4. Does it Compile?

let tuple = (day: 15, month: 8, year: 2015)
let day = tuple.Day

Challenge 5: Find the Error

What is wrong with the following code?

let name = "Matt"
name += " Galloway"

Challenge 6: What is the Type of value?

What is the type of the constant named value?

let tuple = (100, 1.5, 10)
let value = tuple.1

Challenge 7: What is the Value of month?

What is the value of the constant named month?

let tuple = (day: 15, month: 8, year: 2015)
let month = tuple.month

Challenge 8: What is the Value of summary?

What is the value of the constant named summary?

let number = 10
let multiplier = 5
let summary = "\(number) multiplied by \(multiplier) equals \(number * multiplier)"

Challenge 9: Compute the Value

What is the sum of a and b, minus c?

let a = 4
let b: Int32 = 100
let c: UInt8 = 12

Challenge 10: Different Precision 𝜋s

What is the numeric difference between Double.pi and Float.pi?

Key Points

  • Type conversion allows you to convert values of one type into another.
  • Type conversion is required when using an operator, such as the basic arithmetic operators (+, -, *, /), with mixed types.
  • Type inference allows you to omit the type when Swift already knows it.
  • Unicode is the standard for mapping characters to numbers.
  • A single mapping in Unicode is called a code point.
  • The Character data type stores single characters, and the String data type stores collections of characters or strings.
  • You can combine strings by using the addition operator.
  • You can use string interpolation to build a string in place.
  • You can use tuples to group data into a single data type.
  • Tuples can either be unnamed or named. Their elements are accessed with index numbers for unnamed tuples or programmer-given names for named tuples.
  • There are many kinds of numeric types with different storage and precision capabilities.
  • Type aliases can be used to create a new type that is simply a new name for another type.
  • Protocols are how Swift organizes types by describing the operations and properties they share.
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 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