Swift Basics

Swift is a modern, open source programming language.

Installation

You can install Swift by downloading Xcode from the Mac App Store.

To verify the installation, run the following command in the terminal:

1
swift --version

You can create swift file with .swift extension. To run a Swift file, use the following command:

1
swift <filename>.swift

Hello World

1
print("Hello, World!")

Data Types

Swift basic data types are Int, Double, String, Bool, Array, Dictionary, Set, Tuple, Optional, and more.

1
2
3
4
5
6
7
8
9
let a = 10;
let b = 10.0;
let d = "Hello, World!";
let e = true;
let f = [1, 2, 3];
let g = ["a": 1, "b": 2];
let h = Set([1, 2, 3]);
let i = (1, 2, 3);
let j = Optional(1);

Array

Arrays are declared with []. Array is a collection of elements of the same type. Common operations include append, remove, insert, and count.

1
2
3
4
5
6
7
var array = [1, 2, 3];
array.append(4);
array.remove(at: 0);
array.insert(1, at: 0);

print(array);
print(array.count);

Set

1
2
3
4
5
6
7
8
9
// set
var set = Set([1, 2, 3, 4, 5])

// set operations
set.insert(6)
set.remove(1)

print(set)
print(set.contains(2)) // true

Dictionary

1
2
3
4
5
6
7
8
// dictionary
var dict = ["a": 1, "b": 2]

dict["c"] = 3
dict.removeValue(forKey: "a")

print(dict)
print(dict["b"])

Variables and Constants

variables are declared with var, constants are declared with let. You can also declare variables with type annotation.

1
2
3
4
var a = 10;
let b = 10.0;

let names: [String] = ["John", "Jane", "Jack"]

Enum

Enum is a collection of related constants.

1
2
3
4
5
6
7
8
9
10
enum Direction {
case north
case south
case east
case west
}

let direction = Direction.north

print(direction)

If Statement

1
2
3
4
5
6
7
if a > b {
print("a is greater than b")
} else if a < b {
print("a is less than b")
} else {
print("a is equal to b")
}

Switch Statement

1
2
3
4
5
6
7
8
switch a {
case 1:
print("a is 1")
case 2:
print("a is 2")
default:
print("a is not 1 or 2")
}

Loops

1
2
3
for i in 1...5 {
print(i)
}
1
2
3
4
while a > 0 {
print(a)
a -= 1
}

Function

A function is a block of code that performs a specific task. Functions can take parameters and return values.

1
2
3
4
5
6
7
8
9
let names: [String] = ["John", "Jane", "Jack"]

func printArray(arr: [String]) {
for name in arr {
print(name)
}
}

printArray(arr: names)

Function with return value

1
2
3
4
5
6
7
func isPalindrome(s: String) -> Bool {
let str = s.lowercased()
let reversedStr = String(str.reversed())
return str == reversedStr
}

print(isPalindrome(s: "Catac"))

Function with multiple parameters

1
2
3
4
5
func add(a: Int, b: Int) -> Int {
return a + b
}

print(add(a: 1, b: 2))

Function with multiple return values

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func getMinAndMax(arr: [Int]) -> (Int, Int) {
var min = arr[0]
var max = arr[0]
for num in arr {
if num < min {
min = num
}
if num > max {
max = num
}
}
return (min, max)
}

let (min, max) = getMinAndMax(arr: [1, 2, 3, 4, 5])
print("Min: \(min), Max: \(max)")

To skip parameters, use underscore (_).

1
2
3
4
5
6
7
func isPalindrome(_ s: String) -> Bool {
let str = s.lowercased()
let reversedStr = String(str.reversed())
return str == reversedStr
}

print(isPalindrome("Catac"))

Default parameters

1
2
3
4
5
6
func add(a: Int, b: Int = 0) -> Int {
return a + b
}

print(add(a: 1))
print(add(a: 1, b: 2))

Closure - anonymous function. It is a self-contained block of code that can be passed around. Syntax:

1
2
3
{ (parameters) -> return type in
// code
}

Example:

1
2
3
4
5
let numbers = [1, 2, 3, 4, 5]
let evenNumbers = numbers.filter({ (num) -> Bool in
return num % 2 == 0
})
print(evenNumbers)

You can simplify the closure by using the shorthand syntax.

1
2
3
let numbers = [1, 2, 3, 4, 5]
let evenNumbers = numbers.filter({ num in num % 2 == 0 })
print(evenNumbers)

You can also use $0, $1, $2, … to represent the parameters.

1
2
3
let numbers = [1, 2, 3, 4, 5]
let evenNumbers = numbers.filter({ $0 % 2 == 0 })
print(evenNumbers)

Struct

Struct is a custom data type. It is a collection of properties and methods. It is similar to a class, but it is value type.

1
2
3
4
5
6
7
8
9
10
11
12
13
struct Point {
let x: Int
let y: Int

func printPoint() {
print("x: \(x), y: \(y)")
}
}

let p = Point(x: 2, y: 3)
p.printPoint()
print(p.x)
print(p.y)

init method

1
2
3
4
5
6
7
8
9
10
11
12
struct Point {
let x: Int
let y: Int

init(x: Int, y: Int) {
self.x = x
self.y = y
print("Point initialized")
}
}

let p = Point(x: 2, y: 3)

mutating method - can modify the struct. Without this, the struct is immutable. assignment to property ‘self’ is not allowed in a non-mutating method.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct Point {
var x: Int
var y: Int

mutating func moveBy(x: Int, y: Int) {
self.x += x
self.y += y
}
}

var p = Point(x: 2, y: 3)
p.moveBy(x: 1, y: 1)
print(p.x)
print(p.y)

Computed property - property that is calculated on the fly.

1
2
3
4
5
6
7
8
9
10
11
12
13
import Foundation

struct Point {
let x: Int
let y: Int

var distanceFromOrigin: Int {
return Int(sqrt(Double(x * x + y * y)))
}
}

let p = Point(x: 3, y: 4)
print(p.distanceFromOrigin)

static variable - shared by all instances of the struct

1
2
3
4
5
6
7
8
9
10
11
12
struct Point {
static let origin = Point(x: 0, y: 0)
let x: Int
let y: Int

init(x: Int, y: Int) {
self.x = x
self.y = y
}
}

print(Point.origin)

static method - can be called on the struct itself

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct Point {
static let origin = Point(x: 0, y: 0)
let x: Int
let y: Int

init(x: Int, y: Int) {
self.x = x
self.y = y
}

static func printOrigin() {
print(Point.origin)
}
}

Point.printOrigin()

private variable - can only be accessed within the struct

1
2
3
4
5
6
7
8
9
10
11
12
13
struct Point {
private(set) let x: Int
private(set) let y: Int

init(x: Int, y: Int) {
self.x = x
self.y = y
}
}

let p = Point(x: 2, y: 3)
p.x // error
p.y // error

Class

Class is similar to struct, but it is reference type. You can create subclass and override methods.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

class Vehicle {
var numberOfWheels: Int
var numberOfSeats: Int

init(numberOfWheels: Int, numberOfSeats: Int) {
self.numberOfWheels = numberOfWheels
self.numberOfSeats = numberOfSeats
}

func printDescription() {
print("Number of wheels: \(numberOfWheels)")
print("Number of seats: \(numberOfSeats)")
}
}

class Car: Vehicle {
init() {
super.init(numberOfWheels: 4, numberOfSeats: 5)
}

override func printDescription() {
print("This is a car")
super.printDescription()
}
}

let car = Car()
car.printDescription()

Protocol

Protocol is a blueprint of methods, properties, and other requirements that a class, struct, or enum must implement.

Example: protocol Vehicle with required properties and methods. numberOfWheels is a read-only property, numberOfSeats is a read-write property, and printDescription is a method.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
protocol Vehicle {
var numberOfWheels: Int { get }
var numberOfSeats: Int { get set }

func printDescription()
}

struct Car: Vehicle {
var numberOfWheels: Int
var numberOfSeats: Int

init(numberOfWheels: Int, numberOfSeats: Int) {
self.numberOfWheels = numberOfWheels
self.numberOfSeats = numberOfSeats
}

func printDescription() {
print("This is a car")
}
}

var car: Vehicle = Car(numberOfWheels: 4, numberOfSeats: 5)
car.printDescription()
// car.numberOfWheels = 6 // error: number of wheels is a get-only property
car.numberOfSeats = 7
print(car.numberOfWheels)
print(car.numberOfSeats)

Extension

Extension is a way to add new functionality to a class, struct, or enum.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
extension String {
// function
func isPalindrome() -> Bool {
let str = self.lowercased()
let reversedStr = String(str.reversed())
return str == reversedStr
}

// computed property
var reversed: String {
return String(self.reversed())
}

var lines: [String] {
return self.split(separator: "\n").map { String($0) }
}
}

print("racecar".isPalindrome())
print("racecar".reversed)
print("line1\nline2\nline3".lines)

Optional

Optional is a type that can be either a value or nil. It is used to handle the case where a value may not exist.

1
var optionalInt: Int? = nil

optional can be used to handle the case where a value may not exist.

1
2
3
4
5
6
7
let cart: [String: Int] = ["apple": 2, "banana": 3]

if let pearCount = cart["pear"] {
print("Pear count: \(pearCount)")
} else {
print("Pear not found in cart")
}

guard let - used to unwrap an optional value and provide a default value if the optional is nil.

1
2
3
4
5
6
7
8
9
10
11
let cart: [String: Int] = ["apple": 2, "banana": 3]

func printPearCount() {
guard let pearCount = cart["pear"] else {
print("Pear not found in cart")
return
}
print("Pear count: \(pearCount)")
}

printPearCount()