Swift Quick Reference
·9 mins
Table of Contents
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
}
}