Skip to main content

Swift Quick Reference

·9 mins

Hello World #

static func main(_ arguments: [String]?) {
    print("Hello World")
}

Variables and Constants #

// Declaring a constant using the let keyword
let number = 2.0 // Inferred as a Double
// double = 3.0 // Error: You can't reassign to a constant
let doubleNumber: Double = 2.0 // Type specified
// Declaring a variable using the var keyword
var mutableNumber = 1 // Inferred as Int
mutableNumber = 2 // Ok: You can reassign to a variable

String #

// Single line string literal
let greeting = "Hello, World" // Inferred as a String
// Multiline string literal
let greeting = """
Hello,
World
"""
var emptyString = ""
// Mutating a string
var mutableString = "Money"
mutableString += "does'nt fall from the sky!"
// String Interpolation
print("The number is \(number)")
print("Hey \(greeting)")

Array #

// Immutable array infered as [String]
let immutableArray = ["Arya", "Robb"]
// Mutable array
var mutableArray: [String] = ["Sansa", "Bran"]
// Test the membership
let isAryaThere = immutableArray.contains("Arya")
// Access by index
let name: String = immutableArray[0]
// Update item
mutableArray[1] = "Jon" // Crashes if the index is out of range
// Add an item
mutbaleArray.append("Theon") // Add an item at the end
mutbaleArray.insert("Theon", at: 1) // Add an item at index
// Delete by index
let removed = mutbaleArray.remove(at: 1)

Dictionary #

let immutableDict = ["name": "Arya", "brother": "Jon"] // infered as [String: String]
var mutableDict: [String: String] = ["name": "Sansa", "brother": "Robb"]
// Access by key
let name = immutableDict["name"]
// Update value for key
mutableDict["name"] = "Theon"
// Add a new key and value
mutableDict["familyName"] = "Stark"
// Delete by key
let deleted = mutableDict.removeValue(forKey: "name")

Set #

// Sets ignore duplicate items
let immutableSet: Set = ["chocolate", "vanilla", "cream"]
var mutableSet: Set = ["butterscotch", "strawberry"]
// A way to test membership
immutableSet.contains("chocolate")
// Add an item
mutableSet.insert("coffee")
// Remove an item
let removed: String? = mutableSet.remove("strawberry")

Tuple #

// Groups multiple values together
let error = (404, "not found")
// Decomposing a tuple's contents
let (code, reason) = error
// Another way to decompose
let codeByIndex = error.0
let reasonByIndex = error.1
// Ignoring parts of the tuple using
let (_, onlyReason) = error

Loops #

// Iterate over a list or sequence
let items = ["A", "B", "C", "D", "E"]
for item in items {
    print(item)
}
// Iterate over a list or sequence along with index
for (index, item) in items.enumerated() {
    print(index,"-",item)
}
// Iterate over dictionary
let dict = ["name": "Apple", "type": "Fruit"]
for (key, value) in dict {
    print("\(key) = \(value)")
}
// Iterate over a closed range
for i in 0...10 {
    print(i)
}
// Iterate over half-open range
for i in 0..<10 {
    print(i)
}
// While loop
var i = 10
while i > 0 {
    i -= 1
    print(i)
}
// Repeat-while loop
repeat {
    i += 1
    print(i)
} while (i < 10)

Conditionals #

// Using if clause
let weather = "sunny"
if wather == "cloudy" or weather == "partly cloudy" {
    print("Don't go for shopping.")
}
else { // this get executed
    print("Go for shopping.")
}
// Ternary operator
let height = 5.6
let isTall = height > 6.0 ? true : false // false
// Using guard to transfer program control out of scope if one or more conditions are'nt met.
for n in 1...20 {
    guard n % 2 == 0 else {
        continue
    }
    print("\(n) is even")
}
// Using switch to choose between cases
let num = 3
switch num {
    case 1:
    print("Value is One")
    case 2:
    print("Value is Two")
    case 3:
    print("Value is Three")
    default:
    print("Value is Unknown")
}

Functions #

// Void function
func sayHello() {
    print("Hello")
}
// Function with parameter
func sayHello(name: String) {
    print("Hello \(name)!")
}
// Function with default parameter
func sayHello(name: String = "Soumen") {
    print("Hello \(name)!")
}
// Function with default and regular parameter
func sayHello(name: String = "Soumen", age: Int) {
print("\(name) is \(age) years old.")
}
// Function call using just the non default value
sayHello(age: 25)
// Function with parameters and return value
func add(x: Int, y: Int) -> Int {
    return x + y
}
let value = add(x: 2, y: 3)
// If the function contains single expression, the return keyword can be omited
func add(x: Int, y: Int) -> Int {
    x + y
}
// Specifing argument labels
func add(x xVal: Int, y yVal: Int) -> Int {
    return xVal + yVal
}
// Omitting the argument label for one or more parameters
func add(_ x: Int, y: Int) -> Int {
    return x + y
}
let value = add(2, y: 4)
// A function that accepts another function
func doMath(operation: (Int, Int) -> Int, a: Int, b: Int) -> Int {
    return operation(a, b)
}

Closures #

// Closure declaration
let adder: (Int, Int) -> Int = { (x, y) in x + y }
// Closure with shorthand argument names
let square: (Int) -> Int = { $0 * $0 }
// Passing a closure in function
let value = doMath(adder, a: 5, b: 9)

Enumerations #

enum Taste {
    case sweet, sour, salty, bitter, umami
}
let lemonTaste = Taste.sour
// Iterating through an enum class
enum Food: CaseIterable {
    case quinoa, kale, coffee
}
for food in Food.allCases {
    print(food)
}
// Enum with string values
enum Currency: String {
    case euro = "EUR"
    case dollar = "USD"
    case pound = "GBP"
}
// Print the backing value
let euroSymbol = Currency.euro.rawValue
print("The currency symbol for euro is \(euroSymbol)")
// Enum with assiciated values
enum Content {
    case empty
    case text(String)
    case number(Int)
}
// Matching enumeration values with a switch statement
let content = Content.text("Hello")
switch content {
    case .empty:
    print("Value is empty")
    case .text(let value): // Extract the String value
    print("Value is \(value)")
    case number(_) // ignore the Int value
    print("Value is a number")
}

Struct #

struct User {
    var name: String
    var age: Int = 40
}
// An initializer is automatically created to accept the properties of struct
let john = User(name: "John", age: 35)
// Initializer uses default parameter values for any properties they have them
let dave = User(name: "Dave")
// Accessing properties
print("\(john.name) is \(john.age) years old.")

Classes #

class Person {
    let name: String
    // Initializer
    init(name: String) {
        self.name = name
    }
    deinit {
        print("Performing the deinitialization")
    }
    var numberOfLaughs: Int = 0
    func laugh() {
        numberOfLaughs += 1
    }
    var isHappy: Bool {
        numberOfLaughs > 0
    }
}
let david = Person(name: "David")
david.laugh()
let happy = david.isHappy
// Inheritance
class Student: Person {
    var numberOfExams: Int = 0
    // Override iHappy computed property
    override var isHappy: Bool {
        return numberOfLaughs > && numberOfExam > 0
    }
}
let ray = Student("Ray")
ray.numberOfExams = 4
ray.laugh()
let happy = ray.isHappy
// Mark chind as final to prevent subclassing
final class Child: Person { }
// A class must have one designated initializer and can have one or more convenience initializers
class ModeOfTransportation {
    let name: String
    init(name: String) {
        self.name = name
    }
    // Define a convenience inilializer that takes no arguments
    convenience init() {
        self.init(name: "Not Classified")
    }
}
class Vehicle: ModeOfTransportation {
    let wheels: Int
    // Define a designated initializer
    init(name: String, wheels: int) {
        self.wheels = wheels
        super.init(name: name)
    }
    override convenience init(name: String) {
        // Deligate to the internal designated initializer
        self.init(name: name, wheels: 4)
    }
}

Access Control #

// A module is a single accessible distribution of code unit that can be imported by another module using import keyboard.
// You can define the access level for an entity by placing one of the open, public, internal, fileprivate, or private modifiers at the beginning of the entity’s declaration.
// Open — This is where you can access all data members and member functions within the same module(target) and outside of it. You can subclass or override outside the module(target).
// Public — This is the same as open, the only difference is you can't subclass or override outside the module(target).
// Internal — This is the default access level in Swift, it allows all data members and member functions to be accessed within the same module(target) only and restrict access outside the module(target).
// File-private - This is the same as private, the only difference is it allows access in a subclass with in the same file.
// Private — This is where you can access data members and function within its enclosing declaration as well as an extension within the same file. It does not allow access in a subclass with in the same file or in another file.
// Class accessible from another module
public class AccessLevelShowcase {
    // Property accesible from another module
    public var somePublicProperty = 0
    // Property accessible from the module is contained into
    var someInternalProperty = 0
    // Property accessible from its own defining source file
    fileprivate func someFilePrivateMethod() {}
    // Property accessible from its own enclosing declaration
    private func somePrivateMethod() {}
}
class SomeInternalClass {} // implicitly internal

Protocols #

import Foundation
// Codable conformance is the same as conforming seperately to Encodable and Decodable
struct UserInfo: Codable, CustomStringConvertible {
    let username: String
    let loginCount: Int
    
    var description: String {
        return "\(username) has tried to login \(loginCount) time(s)"
    }
}
// Define multiline string literal to represent JSON
let json = """
{"username": "David", "loginCount": 6}
"""
let decoder = JSONDecoder()
// Transforming string to its data representation
let data = json.data(using: .utf8)
let userInfo = try! decoder.decode(UserInfo.self, from: data)
print(userInfo)
// Using encodable to serialize a struct
let encoder = JSONEncoder()
let userInfoData  = encoder.encode(userInfo)
// Transforming data to its string representation
let str = String(data: userInfoData, encoding: .utf8)
print(str)

Extensions #

// Extensions add new functionality to existing class, struct, protocol and ennumerations
extension String {
    var boolValue: Bool {
        if self == "1" || self == "true" {
            return true
        }
        return false
    }
}
let isTrue = "0".boolValue // False

Error Handling #

// Representing an error
enum PrinterError: Error {
    case outOfPaper
    case coverOpen
    case noToner
}
func print(in printerName: String) throws -> String {
    if printerName == "Has No Toner" {
        throw PrinterError.noToner
    }
    return "Printed Successfully"
}
let message: String
do {
    message = try print(in: "Epson Printer")
}
catch PrinterError.outOfPaper {
    print("Printer is out of paper.")
}
catch PrinterError.coverOpen {
    print("Printer cover open.")
}
catch PrinterError.noToner {
    print("Printer has no toner")
}
catch {
    print("Generic error")
}
// If an error is thrown while evaluating the try? expression, the value of the expression is nil
let nillableMessage = try? print(in: "Has No Toner")
// If an error is thrown you will get a runtime error, otherwise the value
let throwableMessage = try! print(in: "Star Printer")

Macros #

// Freestanding Macro (Starts with #)
func myFunction() {
    print("Currently running \(#function)")
}
// Attached Macro (Starts with @)
@OptionSet<Int>
struct SundaeToppings {
    private enum Options: Int {
        case nuts
        case cherry
        case fudge
    }
}