The Swift Language

  1. Variables and constants
  2. Built-in data types
  3. Structure data types
  4. Control structure
  5. Optional values
  6. Arrays and dictionaries
  7. Objects and their methods
  8. Protocols and delegates

The one-day version of this course mentions only

  1. Variable and constant declaration
  2. String Interpolation
  3. Structure data types
  4. Optional values
  5. Arrays and dictionaries

Apple’s online documentation for Swift 4.2:

  1. Swift Tour (simple)
  2. Language Guide (more detailed)
  3. Language Reference (the grammar)
  4. Standard Library Reference (including functions such as print) and API Reference
  5. Using Swift with Cocoa and Objective-C
  6. Swift Resources
  7. SwiftDoc.org

Variables and constants

A variable is a container inside the computer, usually containing one number. There are many types of variables and the simplest type is named Int. A variable of this type can contain only a number that is an integer (whole number). It cannot contain a number that has a fraction.

var i: Int = 10;   //Create a variable named i.  (This is a comment.)
let j: Int = 20;   //Create a constant named j.

Since the numbers 10 and 20 have no decimal point and fraction, the computer can figure out that they’re integers. We can therefore omit the type annotations:

var i = 10;	//Create a variable named i.
let j = 20;	//Create a constant named j.

But I would feel safer if you wrote the type annotation. The semicolon is also optional.

We can change the value (contents) of a variable, but not the value of a constant. That’s why they’re called “variable” and “constant”.

var i: Int = 10; //Create the variable and put 10 into it.
i = 20;          //Change the value of the variable to 20.
i = 30 + 40;     //Change the value of the variable to 70.
i = 2 * i;       //Change the value of the variable to 140.
i = i + 1;       //Change the value of the variable to 141.
i += 1;          //Change the value of the variable to 142.  (Swift 5 does not have the ++ or -- operators).

Built-in data types

The name of a variable can be more than one letter. The number 9,223,372,036,854,775,807 is pronounced “9 quintillion, 223 quadrillion, 372 trillion, 36 billion” etc.

var i: Int = 10;                         //occupies 64 bits on iPhone 8 and iPhone XR, 32 bits on my 5th generation iPod touch
let maximum: Int =  9223372036854775807; //maximum on iPhone 6s: 263 - 1
let minimum: Int = -9223372036854775808; //minimum on iPhone 6s: -263

let maximum: Int = 9_223_372_036_854_775_807; //easier way to write the same thing
let maximum: Int = Int.max;              //easiest way to write the same thing
let minimum: Int = Int.min;
var f: Float = 3.14159;           //single precision can hold up to 6 significant digits
var d: Double = 3.14159265358979; //double precision can hold up to 15 significant digits

var length: CGFloat = 10.25;      //for lengths and coördinates on the screen; CG stands for Core Graphics.
var latitude: CLLocationDegrees = 40.75; //CL stands for Core Location
var b: Bool = true;               //or false.  Named after George Boole.
var c: Character = "A";           //exactly one character, no more and no less
var s: String = "Hello, world!";  //any number of characters, including zero of them

String interpolation and the print function

A program can be divided into sections called functions. Each function has a name. For example, there’s a function named print. This function will print some text; that’s why it’s named “print”.

An item of information that we feed into a function is called a parameter of the function. For print, the parameter is a String containing the line of text that we want to print. Write the parameter in (parentheses) after the function’s name.

let i: Int = 10;
let j: Int = 20;

var s: String = "The value of i is i."; //Put "The value of i is i." into s.
s = "The value of i is \(i).";          //Put "The value of i is 10." into s.
s = "The value of i+j is \(i+j).";      //Put "The value of i+j is 30." into s.

print("New York");                      //Print "New York" to standard output.
print(s);                               //Print "The value of i+j is 30.".
print("The value of i+j is \(i+j).");   //Print "The value of i+j is 30.".

A Swift playground

Another way to see the value of a Swift variable is by creating a playground file. (See also Playgrounds on iPad.)

Launch Xcode. (I have Xcode version 14.2 (14C18).)
File → New → Playground…
Choose a template for your new playground:
iOS
Blank
Next
Name: MyPlayground
Platform: iOS
Next
Save the new file MyPlayground.playground on your Desktop.
Create

import UIKit

var str = "Hello, playground"

var i: Int = 10;
print("The value of i is \(i).");

i = 10 + 20;
i = i + 10;
i += 10;

10 + 20;
1 / 3;
1.0 / 3.0;
1.0 / 0.0;

Int.max;
Double.pi;

To see the output of your prints in a separate panel that you can copy and paste,
View → Debug Area → Show Debug Area

To save the .playground file and get out of Xcode,

File → Save
Xcode → Quit Xcode

Structure data types

A big variable that contains little variables is called a structure. The little variables stored inside the structure are called the stored properties (or fields) of the structure. Think of them as the structure’s internal organs.

CGPoint and CGSize are two types of structure that each have two stored properties of type CGFloat. But the structures are used for totally different purposes. The properties of a CGPoint might be negative, but the properties of a CGSize should never be negative. (CG stands for Core Graphics.)

The CGPoint function is a memberwise initializer that takes two parameters. The 0.0 and 0.0 are arguments. The x: and y: are argument labels. They remind you of the purpose of the arguments.

var p: CGPoint = CGPoint(x: 0.0, y: 0.0);            //create a structure p holding the values 0.0 and 0.0
var s: CGSize = CGSize(width: 375.0, height: 667.0); //create a structure s holding the values 375.0 and 667.0

The stored properties inside a CGPoint are named x and y. In this case, the stored property names are the same as the argument labels of the function that created the structure variable. Write the name of the structure variable to the left of the dot, and the name of the property to the right.

var p: CGPoint = CGPoint(x: 0.0, y: 0.0);
var x: CGFloat = p.x;
var y: CGFloat = p.y;

The stored properties inside a CGSize are named width and height.

var s: CGSize = CGSize(width: 375.0, height: 667.0);
var w: CGFloat = s.width;
var h: CGFloat = s.height;
//Find the midpoint between point a and point b.
let a: CGPoint = CGPoint(x: 10.0, y: 20.0);
let b: CGPoint = CGPoint(x: 30.0, y: 40.0);

let midpoint: CGPoint = CGPoint(x: (a.x + b.x) / 2.0, y: (a.y + b.y) / 2.0);
print("The midpoint is \(midpoint).");

The output is

The midpoint is (20.0, 30.0).

In the location manager app, the properties inside a CLLocationCoordinate2D structure will be named latitude and longitude. (CL stands for Core Location.) A structure is not limited to containing two properties. A tailor might need a structure containing bust, waist, hips. A weather report might need a structure containing temperature, humidity, barometric pressure, and wind speed.

A structure can contain smaller structures as its properties. For example, a CGRect contains a CGPoint named origin and a CGSize named size.

var r: CGRect = CGRect(x: 0.0, y: 0.0, width: 375.0, height: 667.0);
var p: CGPoint = r.origin;   //The properties inside of r
var s: CGSize = r.size;      //are named r.origin and r.size

//An expression can have more than one dot,
//like the expression 10+20+30 has more than one plus.
var x: CGFloat = p.x;
var y: CGFloat = r.origin.y;

Here’s a diagram of the above structure r and its contents.

Control structure

By default, the iPhone will execute every statement of the program exactly once, starting at the top and working its way down to the bottom. To do anything other than this straight-line execution, we have to use control structure statements.

if statements

We don’t have to write (parentheses) around the expression x < 0, but we do have to write the {curly braces} around the block of statements that is to be executed or skipped.

let x: Int = 10;
var message: String;
var sign: Int;

if x < 0 {
	message = "x is negative";
	sign = -1;
}
//Steer the computer in one of two possible directions.
//In other words, execute one of two possible blocks of statements.

if x < 0 {
	message = "x is negative";
	sign = -1;
} else {
	message = "x is non-negative";
	sign = 0;
}
//Steer the computer in one of three possible directions.

if x < 0 {
	message = "x is negative";
	sign = -1;
} else if x == 0 {			//== tests for equality, no space between them
	message = "x is zero";
	sign = 0;
} else {
	message = "x is positive";
	sign = 1;
}

The value of the expression 2018 / 400 is 5 (the quotient, truncated to an integer).
The value of the expression 2018 % 400 is 18 (the remainder).

//Steer the computer in one of four possible directions.

let year: Int = 2018;
var isLeap: Bool;

if year % 400 == 0 {
	isLeap = true;		//year is a multiple of 400
} else if year % 100 == 0 {
	isLeap = false;		//year is a multiple of 100, but not of 400
} else if year % 4 == 0 {
	isLeap = true;		//year is a multiple of 4, but not of 100 or 400
} else {
	isLeap = false;		//year is not a multiple of 4, 100, or 400
}

if isLeap {
	print("\(year) is a leap year.");
} else {
	print("\(year) is not a leap year.");
}

The output is

2018 is not a leap year.

The Metro North evacuation instructions steer the computer in one of four possible directions:

if it is possible to remain inside the train {
	remain inside the train;
} else if you are able to go to next car through end doors {
	go to next car through end doors;
} else if you are able to open the side door and get out {
	open the side door and get out;
} else {
	go out emergency windows;
}
//Steer the computer in one of four possible directions.

var n: Int = 23;	//must be non-negative
var lastDigit: Int = n % 10;
var suffix: String;	//ordinal suffix

if lastDigit == 1 {
	suffix = "st";
} else if lastDigit == 2 {
	suffix = "nd";
} else if lastDigit == 3 {
	suffix = "rd";
} else {
	suffix = "th";
}

print("\(n)\(suffix)");
23rd

What is the smallest positive integer for which the above code gives the wrong output? The following || means “or”.

//Steer the computer in one of five possible directions.

var n: Int = 211;	//must be non-negative
var lastDigit: Int = n % 10;
var lastTwoDigits: Int = n % 100;
var suffix: String;	//ordinal suffix

if lastTwoDigits == 11 || lastTwoDigits == 12 || lastTwoDigits == 13 {
	suffix = "th";
} else if lastDigit == 1 {
	suffix = "st";
} else if lastDigit == 2 {
	suffix = "nd";
} else if lastDigit == 3 {
	suffix = "rd";
} else {
	suffix = "th";
}

print("\(n)\(suffix)");
211th

Nested if statements

Do we always need to perform both comparisons? Performance bug. <= means “less than or equal to”.

let profit: Int = 100;
let loss: Int = 110;

if profit <= loss {
	print("We're not making any money.");
}

if profit < loss {
	print("In fact, we're losing money.");
}
We're not making any money.
In fact, we're losing money.
let profit: Int = 100;
let loss: Int = 110;

if profit <= loss {
	print("We're not making any money.");
	if profit < loss {
		print("In fact, we're losing money.");
	}
}

Do we always need to perform both comparisons? Performance bug.

let profit: Int = 100;
let loss: Int = 110;

if profit > loss {
	print("We're making money.");
} else {
	print("We're not making any money.");
}

if profit < loss {
	print("In fact, we're losing money.");
}
We're not making any money.
In fact, we're losing money.
let profit: Int = 100;
let loss: Int = 110;

if profit > loss {
	print("We're making money.");
} else {
	print("We're not making any money.");
	if profit < loss {
		print("In fact, we're losing money.");
	}
}

Top heavy if/else statements

An if/else statement is easiest to read when the smaller block is above the bigger one.

var x: Int = 10;

//good

if x == 10 {
	print("+---+");
	print("|   |");
	print("+---+");
} else {
	print("+---+");
	print("|   |");
	print("|   |");
	print("+---+");
}
What to do when the smaller block is below the bigger one?
var y: Int = 10;

//bad

if y == 10 {
	print("+---+");
	print("|   |");
	print("|   |");
	print("+---+");
} else {
	print("+---+");
	print("|   |");
	print("+---+");
}
Simply replace the comparison operator with its opposite.
== and != are a pair of opposites.
< and >= are a pair of opposites.
> and <= are a pair of opposites.
var y: Int = 10;

//good

if y != 10 {
	print("+---+");
	print("|   |");
	print("+---+");
} else {
	print("+---+");
	print("|   |");
	print("|   |");
	print("+---+");
}

for loops and ranges of numbers

The square brackets in the expression [0, 1, 2] create an array containing the numbers 0, 1, 2. (See also the underscore _).

for var i: Int in [0, 1, 2] {
	print("She loves you");
	print("Yeah!");
	print("Yeah!");
	print("Yeah!");
}
She loves you
Yeah!
Yeah!
Yeah!
She loves you
Yeah!
Yeah!
Yeah!
She loves you
Yeah!
Yeah!
Yeah!

Instead of using the array [0, 1, 2], we can get exactly the same output with a range. See

  1. range with for loops in the Swift Tour
  2. range with for loops in the Language Guide
  3. range operators in the Language Guide
  4. Range as a structure

The expression 0 ... 3 represents the range of numbers 0, 1, 2, 3.
The expression 0 ..< 3 represents the range of numbers 0, 1, 2.

for var i: Int in 0 ..< 3 {
	print("She loves you");
	print("Yeah!");
	print("Yeah!");
	print("Yeah!");
}

The computer can figure out that i is an Int variable:

for i in 0 ..< 3 {
	print("She loves you");
	print("Yeah!");
	print("Yeah!");
	print("Yeah!");
}

Nested loops:

for i in 0 ..< 3 {
	print("She loves you");
	for j in 0 ..< 3 {
		print("Yeah!");
	}
}
She loves you
Yeah!
Yeah!
Yeah!
She loves you
Yeah!
Yeah!
Yeah!
She loves you
Yeah!
Yeah!
Yeah!

A loop that prints numbers:

for i in 0 ..< 5 {
	print("i = \(i)");
}
i = 0
i = 1
i = 2
i = 3
i = 4

A range does not necessarily have to start with 0:

for h in 2 ... 8 {
	print("\(4 * h) pierogies feed \(2 * h) people or \(h) Hungarians.");
}
8 pierogies feed 4 people or 2 Hungarians.
12 pierogies feed 6 people or 3 Hungarians.
16 pierogies feed 8 people or 4 Hungarians.
20 pierogies feed 10 people or 5 Hungarians.
24 pierogies feed 12 people or 6 Hungarians.
28 pierogies feed 14 people or 7 Hungarians.
32 pierogies feed 16 people or 8 Hungarians.

To count down, we must use stride instead of a range. We can feed arguments of type Int into the stride function because the data type Int is actually a structure that conforms to the protocol Strideable. But Strideable is not mentioned in the developer.apple.com documentation for Int. But it is mentioned in the SwiftDoc.org documentation for Int.

for b in stride(from: 100, through: 1, by: -1) {
	print("\(b) bottles of beer on the wall,");
	print("\(b) bottles of beer--");
	print("If one of those bottles should happen to fall,");
	print("\(b - 1) bottles of beer on the wall.");
	print();	//Skip a line.
}
100 bottles of beer on the wall,
100 bottles of beer--
If one of those bottles should happen to fall,
99 bottles of beer on the wall.

99 bottles of beer on the wall,
99 bottles of beer--
If one of those bottles should happen to fall,
98 bottles of beer on the wall.

98 bottles of beer on the wall,
98 bottles of beer--
If one of those bottles should happen to fall,
97 bottles of beer on the wall.

etc.

1 bottles of beer on the wall,
1 bottles of beer--
If one of those bottles should happen to fall,
0 bottles of beer on the wall.

Driving north from New York City on the New York State Thruway:

for a in stride(from: 108, through: 48, by: -10) {
	print("+--------------+");
	print("| Albany    \(a) |");
	print("| Montreal \(a + 220) |");
	print("| Buffalo  \(a + 280) |");
	print("+--------------+");
	print();   //print an empty line (i.e., just a newline character)
}
+--------------+
| Albany    108 |
| Montreal 328 |
| Buffalo  388 |
+--------------+

+--------------+
| Albany    98 |
| Montreal 318 |
| Buffalo  378 |
+--------------+

+--------------+
| Albany    88 |
| Montreal 308 |
| Buffalo  368 |
+--------------+

+--------------+
| Albany    78 |
| Montreal 298 |
| Buffalo  358 |
+--------------+

+--------------+
| Albany    68 |
| Montreal 288 |
| Buffalo  348 |
+--------------+

+--------------+
| Albany    58 |
| Montreal 278 |
| Buffalo  338 |
+--------------+

+--------------+
| Albany    48 |
| Montreal 268 |
| Buffalo  328 |
+--------------+

See multiline string literals with triple quotes. The format is one big string consisting of six lines (the last line is empty, i.e., consists of just a newline character). The String(format:) function (whose name is really init) returs the same string, but with each %3d replaced by a three-digit number in decimal (as opposed to octal or hex).

let format: String = """
+--------------+
| Albany   %3d |
| Montreal %3d |
| Buffalo  %3d |
+--------------+

""";

for a in stride(from: 108, through: 48, by: -10) {
	print(String(format: format, a, a + 220, a + 280));
}
+--------------+
| Albany   108 |
| Montreal 328 |
| Buffalo  388 |
+--------------+

+--------------+
| Albany    98 |
| Montreal 318 |
| Buffalo  378 |
+--------------+

etc.

+--------------+
| Albany    48 |
| Montreal 268 |
| Buffalo  328 |
+--------------+

Optional values: question mark and exclamation point

The only thing the following variable i can contain is an integer.

var i: Int = 10; //born containing the number 10
i = 20;          //change it to 20
i = 10;          //change it back to 10
print("The value of i is \(i).");

The following variable can contain either an integer or the special value nil, which is not an integer. nil stands for “no value”.

var i: Int? = 10;	//born containing the number 10.
i = 20;			//change it to 20
i = nil;		//change it to nil
i = 10;			//change it back to 10

if i == nil {
	print("i is nil.");
} else {
	print("i! is \(i!)."); //The exclamation point "unwraps" (i.e., gets) the non-null value.
	print("i is \(i).");   //Try to print it without the exclamation point.
}
i! is 10.
i is Optional(10).

The exclamation point can be applied only to an optional value that is not equal to nil.

var i: Int? = nil;    //born containing nil
print("i is \(i!)."); //causes fatal error
Fatal error: Unexpectedly found nil while unwrapping an Optional value

Use optional binding to unwrap the value that’s in i once and for all, without using an exclamation point.

var i: Int? = 10;

if var j: Int = i {
	//Arrive here if i was not nil.
	//j now contains the Int that was in i.
	//Since j is not an optional variable,
	//we can use j without writing an exclamation point.
	print("j contains \(j).");
	j += 1;
	print("And now j contains \(j).");
} else {
	//Arrive here if i was nil.
	//In this case, the variable j was never created.
	print("i was nil.");
}	//j cannot be mentioned below this point.

print("We are now done examining i, and can continue on to something else.");
j contains 10.
And now j contains 11.

Whether or not the above i is nil, the code eventually finishes examining i and continues on to something else. If you want to halt the program if i is nil, use guard/else.

var i: Int? = 10;
guard let j: Int = i else {
	//Arrive here if i was nil.
	//In this case, the variable j was never created.
	print("i was nil.  Something is probably wrong.");
	return;   //assuming all this code was inside a function; or throw;
}

//Arrive here only if i was not nil.
print("j = \(j)");

An implicitly unwrapped optional does not need an exclamation point to unwrap it.

//i and j are both optionals.
var i: Int? = 10;   //must write an ! in order to unwrap i
var j: Int! = 20;   //j can be unwraped without writing !

var k: Int;

k = i!;   //Put 10 into k.  Would cause fatal error if i == nil
k = j;    //Put 20 into k.  Would cause fatal error if j == nil

Arrays and dictionaries

Three of the Objective-C collection classes have been built into the language Swift: sets, arrays, and dictionaries.

An array

Use the count property of an array to find out how many elements are in the array. An array is actually a structure whose count property is inherited from the count property of protocol Collection.

The value of the expression 2018 / 12 is 168 (the quotient, truncated, if necessary, to an integer).
The value of the expression 2018 % 12 is 2 (the remainder, in the range 0 to 11 inclusive).

let animals: [String] = [	//an array containing 12 Strings
	"monkey",    // 0
	"rooster",   // 1
	"dog",       // 2
	"pig",       // 3
	"rat",       // 4
	"ox",        // 5
	"tiger",     // 6
	"hare",      // 7
	"dragon",    // 8
	"snake",     // 9
	"horse",     //10
	"sheep"      //11
];

print("The number of animals is \(animals.count).");
print("The first animal is \(animals[0]).");
print("The second animal is \(animals[1]).");
print("The last animal is \(animals[animals.count - 1]).");   //or use the optional .last property

let year: Int = 2018;
print("\(year) is the year of the \(animals[year % animals.count]).");
The number of animals is 12.
The first animal is monkey.
The second animal is rooster.
The last animal is sheep.
2018 is the year of the dog.
print("The last animal is \(animals[animals.count]).");
Fatal error: Index out of range

Properties that are optional values

let animals: [String] = [	//an array containing 12 Strings
	"monkey",    // 0
	"rooster",   // 1
	"dog",       // 2
	"pig",       // 3
	"rat",       // 4
	"ox",        // 5
	"tiger",     // 6
	"hare",      // 7
	"dragon",    // 8
	"snake",     // 9
	"horse",     //10
	"sheep"      //11
];

print("count is \(animals.count)");
print("first is \(animals.first!)");
print("last is \(animals.last!)");
count is 12
first is monkey
last is sheep
let liberalRepublicans: [String] = [String]();   //Call the init method that creates an empty array.
print("count = \(liberalRepublicans.count)");

if var f: String = liberalRepublicans.first {
	print("f = \(f)");	//We skip this print because the array is empty.
}
count = 0

Loop through an array

//The variable animal contains a different String each time around the loop.

for var animal: String in animals {
	print(animal);
}
monkey
rooster
dog
pig
rat
ox
tiger
hare
dragon
snake
horse
sheep

The computer can figure out that animal is a String variable:

for animal in animals {
	print(animal);
}

Let’s print the subscript as well as the value of each element. The expression (index, value) is a tuple, a datatype whose name comes from double, triple, quadruple, quintuple, etc. A tuple is a sort of informal structure that holds two or more values. We can call the enumerated method of the array because struct Array conforms to protocol Collection, which inherits from protocol Sequence, which has the instance method enumerated.

for (index, value) in animals.enumerated() {
	print("\(index) \(value)");
}
0 monkey
1 rooster
2 dog
3 pig
4 rat
5 ox
6 tiger
7 hare
8 dragon
9 snake
10 horse
11 sheep

The value of the expression 2018 % 10 is 8.
The value of the expression 2018 / 10 is 201.
The value of the expression 201 % 10 is 1.
The value of the expression 201 / 10 is 20. Etc.

//Four arrays of Strings.
let ones: [String]      = ["", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"];
let tens: [String]      = ["", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"];
let hundreds: [String]  = ["", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"];
let thousands: [String] = ["", "M", "MM", "MMM"];

var n: Int = 2018;

if n > 0 && n < 4000 {
	let o: Int = n % 10;	//let o be the rightmost digit of n
	n /= 10;		//or n = n / 10; chop the rightmost digit off of n
	let t: Int = n % 10;	//let t be the rightmost surviving digit of n
	n /= 10;
	let h: Int = n % 10;
	n /= 10;
	let th: Int = n % 10;

	print("\(thousands[th])\(hundreds[h])\(tens[t])\(ones[o])");
}
MMXVIII
//A big array containing four little arrays.
//Each little array contains 10 Strings.
        
let bigArray: [[String]] = [
	["", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"],
	["", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"],
	["", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"],
	["", "M", "MM", "MMM"]
];
        
var n: Int = 2018;
var roman: String = "";
        
if n > 0 && n < 4000 {
	for littleArray in bigArray {
		roman = littleArray[n % 10] + roman;
		n /= 10;   //means n = n / 10
	}
	print(roman);
}

Incidentally, here’s how to get the current year.

let date: Date = Date(); //Call the no-parameter init method of class Date
let calendar: Calendar = Calendar.current;
let year: Int = calendar.component(Calendar.Component.year, from: date);
print(year);
2018

Look up a key in a dictionary

let notes: [String: String] = [		//a dictionary containing two parallel columns of Strings
	"do":  "deer, a female deer",
	"re":  "drop of golden sun",
	"me":  "name I call myself",
	"fa":  "long, long way to run",
	"sol": "needle pulling thread",
	"la":  "note to follow sol",
	"ti":  "drink with jam and bread"
];

let key: String = "me";
let value: String? = notes[key];	//an optional String--it might be nil

if value == nil {
	print("There is no note named \(key).");
} else {
	print("\(key): a \(value!)");
}
me: a name I call myself

The following loop is guaranteed to print all of them, but their order is unpredictable. The expression (key, value) is a tuple. See the dictionary in Switch.

for (key, value) in notes {
	print("\(key): a \(value)");
}
me: a name I call myself
do: a deer, a female deer
me: a name I call myself
sol: a needle pulling thread
ti: a drink with jam and bread
re: a drop of golden sun
fa: a long, long way to run
la: a note to follow sol

Objects and their methods

Create an object

Create an object by calling an init method of the object’s class.

//Call the init method of MyClass.  This method takes no parameters.
let myObject: MyClass = MyClass();

let date: Date = Date();	//example from Hello app
print(date);
2018-10-13 02:43:57 +0000

An init method might take a parameter such as the following f. The frame: is an argument label. It reminds us of the purpose of the parameter.

let f: CGRect = CGRect(x: 0, y: 0, width: 80, height: 40);

//A UILabel is a rectangular object that holds one line of text.
//Call an init method of class UILabel and pass it the parameter f.
//The parameter is preceded by an argument label.
//(This init method was inherited by class UILabel from class UIView.)

let label: UILabel = UILabel(frame: f);

//Call an init method of class UISwipeGestureRecognizer.  Pass it two parameters.
//Each parameter is preceded by an argument label.
//(This init method was inherited by class UISwipeGestureRecognizer from class UIGestureRecognizer.)

let recognizer: UISwipeGestureRecognizer =
	UISwipeGestureRecognizer(target: self, action: "swipe:");

A digression on type conversion

Numeric type conversion uses the same syntax as initialization, but without an argument label.

let d: Double = 3.14159265358979;	//could say Double.pi instead of 3.14159265358979
let i: Int = Int(d);			//Put 3 into i.

Two examples from Button:

/*
The constant kSystemSoundID_Vibrate is an enum,
but the parameter of the
function AudioServicesPlaySystemSound must be a SystemSoundID (which is another
name for UInt32).
*/
AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate));
/*
The function AudioServicesCreateSystemSoundID returns an OSStatus, which we want
to compare to the enum kAudioServicesNoError.
*/
let status: OSStatus = AudioServicesCreateSystemSoundID(url, &sid);

if status == OSStatus(kAudioServicesNoError) {
	AudioServicesPlaySystemSound(sid);
}

Call a method of an object

Write the name of the object, a dot, the name of the method, and the parameter list in parentheses. The first parameter will usually not have an argument label, because the purpose of the first parameter will be explained by the name of the method. The remaining parameters might have argument labels.

//Where did the finger touch the screen?
let point: CGPoint = touch.locationInView(self);

//Does the set object contain the string "New York"?
let bool: Bool = set.containsObject("New York");

s.drawAtPoint(point, withAttributes: attributes);

In-Out parameters

An in-out parameter is one that can be written as well as read. The examples we will see today are in Hello and Switch. See Error Handling. NS stands for NextSTEP.

var s: String;
var error: NSError?;	//Must be var, can't be let.  Born containing nil.

//The ampersand allows the method to give a value to the parameter.

let contents: String? = String(contentsOfURL: url!,
	encoding: NSUTF8StringEncoding,
	error: &error);

if contents != nil {
	s = contents!;
} else if error != nil {
	s = error!.localizedDescription;
} else {
	s = "unknown error";
}
var error: NSError?
let player: AVAudioPlayer = AVAudioPlayer(contentsOfURL: url, error: &error);

if error != nil {
	print("could not create AVAudioPlayer: \(error!)");
}

Another digression on type conversion

The return value of a method might have to be downcast (converted) to a more specific data type. The same is true for a value in an array. Here is an example from Set.

//The method anyObject can return an object of any type.
let s: String? = mySet.anyObject() as? String;
let t: String = mySet.anyObject() as! String;	//as! causes fatal error if anyObject returns nil

Call a method of a class

Most methods belong to a particular object. These are called the instance methods of the object. Some methods belong to an entire class of objects, rather than to one particular object. These are called type methods. We often call a type method to get a reference to (i.e., make contact with) an existing object of the type method’s class. Here are the first examples we will see.

//We are not creating the yellow color: it already exists.
//We are merely getting a reference to it.
let color: UIColor = UIColor.yellowColor();

let font: UIFont = UIFont.systemFontOfSize(32);
let screen: UIScreen = UIScreen.mainScreen();
let device: UIDevice = UIDevice.currentDevice();
let application: UIApplication = UIApplication.sharedApplication();
let fileManager: NSFileManager = NSFileManager.defaultManager();

Call a function that belongs to no object

We have seen several functions that are orphans. They belong to no object.

print();           //Print a newline character to the standard output.
print("New York"); //Print a line, followed by a newline.

var y: Double = sin(M_PI / 2);
var y: Double = cos(M_PI / 2);

Closures

A closure is a group of Swift statements in {curly braces} passed as a parameter to a method or other function. We will see a closure passed to the function dispatch_after in Hello and Tap.

//t represents the time that is one second from now.
//NSEC_PER_SEC is the number of nanoseconds per second (1,000,000,000).
let t: dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW, Int64(NSEC_PER_SEC));

//Call myFunction one second from now.
dispatch_after(t, dispatch_get_main_queue(), {myFunction();});

Create a function that belongs to no object

The \t is the tab character. Lesson 7 of Intro to App Development with Swift illustrates a function with Row, Row, Row Your Boat.

print("There's a man who leads a life of danger");
print("To everyone he meets he stays a stranger");
print("With every move he makes, another chance he takes");
print("Odds are he won't live to see tomorrow.");
print();

print("\tSecret Agent Man, Secret Agent Man");
print("\tThey've given you a number, and taken 'way your name.");
print();

print("Beware of pretty faces that you find");
print("A pretty face can hide an evil mind");
print("Be careful what you say, or you'll give yourself away");
print("Odds are you won't live to see tomorrow.");
print();

print("\tSecret Agent Man, Secret Agent Man");
print("\tThey've given you a number, and taken 'way your name.");
print();

//guitar solo

print("\tSecret Agent Man, Secret Agent Man");
print("\tThey've given you a number, and taken 'way your name.");
print();

print("Swinging on the Riviera one day");
print("Lying in a Bombay alley the next day");
print("Don't let the wrong words slip while kissing persuasive lips");
print("Odds are you won't live to see tomorrow.");
print();

print("\tSecret Agent Man, Secret Agent Man");
print("\tThey've given you a number, and taken 'way your name.");
print();

print("Secret Agent Man.");
There's a man who leads a life of danger
To everyone he meets he stays a stranger
With every move he makes, another chance he takes
Odds are he won't live to see tomorrow.

	Secret Agent Man, Secret Agent Man
	They've given you a number, and taken 'way your name.

Beware of pretty faces that you find
A pretty face can hide an evil mind
Be careful what you say, or you'll give yourself away
Odds are you won't live to see tomorrow.

	Secret Agent Man, Secret Agent Man
	They've given you a number, and taken 'way your name.

	Secret Agent Man, Secret Agent Man
	They've given you a number, and taken 'way your name.

Swinging on the Riviera one day
Lying in a Bombay alley the next day
Don't let the wrong words slip while kissing persuasive lips
Odds are you won't live to see tomorrow.

	Secret Agent Man, Secret Agent Man
	They've given you a number, and taken 'way your name.

Secret Agent Man.
func chorus() {
	print("\tSecret Agent Man, Secret Agent Man");
	print("\tThey've given you a number, and taken 'way your name.");
	print();
}

print("There's a man who leads a life of danger");
print("To everyone he meets he stays a stranger");
print("With every move he makes, another chance he takes");
print("Odds are he won't live to see tomorrow.");
print();

chorus();

print("Beware of pretty faces that you find");
print("A pretty face can hide an evil mind");
print("Be careful what you say, or you'll give yourself away");
print("Odds are you won't live to see tomorrow.");
print();

chorus();

//guitar solo

chorus();

print("Swinging on the Riviera one day");
print("Lying in a Bombay alley the next day");
print("Don't let the wrong words slip while kissing persuasive lips");
print("Odds are you won't live to see tomorrow.");
print();

chorus();

print("Secret Agent Man.");

Inheritance

We can create a new class of objects that has all of the features (properties, methods, etc.) of an existing class of objects, plus additional features. The existing class is called the superclass and the new class is called the subclass.

An object of the subclass actually contains a smaller object of the superclass inside of it: that’s how the subclass object gets all the features of the superclass object. Code that creates a subclass object must therefore remember to execute the code that creates the superclass object. In other words, the init method of a subclass must always call the init method of the superclass.

	init() {
		super.init()
		//write code here to create the rest of the subclass object
	}

Protocols and Delegates

A protocol is a list of requirements that a class might have to fulfill. For example, a class that conforms to the protocol UIApplicationDelegate has to have a method named application(_:didFinishLaunchingWithOptions:). (The didFinishLaunchingWithOptions: is an argument label; we will consider it to be part of the method’s name.) Strictly speaking, this method is actually an optional method of protocol UIApplicationDelegate, but you probably want to define it anyway. A protocol in Swift is similar to an interface in Java.

An object can be stimulated in many ways. It can be touched by a finger, or it can reach the end of the audio file that it is playing. When the object is stimulated, we can arrange for it to automatically call a method belonging to another object, called the delegate of the original object. A delegate must belong to a class that conforms to a protocol. The first three examples we will see are

  1. Hello (and every other app): the AppDelegate conforms to the protocol UIApplicationDelegate.
  2. Switch: the ViewController will conform to the protocol AVAudioPlayerDelegate.
  3. TextField: the ViewController conforms to the protocol UITextFieldDelegate.