Swift Cheat Sheet (Updated)

Updated: March 5, 2023 By: Khue Post a comment

This comprehensive Swift cheat sheet covers the key concepts and most commonly used language features, syntax, and best practices (note that programming experience is required to get the most out of the cheat sheet).

Basic Syntax

Comments

// This is a single line comment

/*
This is a
multi-line
comment
*/

Constants and Variables

let constant = "Hello" // Immutable
var variable = "World" // Mutable

variable = "Sling Academy" // Allowed

// Constants can't be changed once they're initialized
// constant = "Goodbye" // Error

Basic Data Types

// Integers
let integer: Int = 42 // 64-bit on all platforms

let uinteger: UInt = 42 // Unsigned integer

let int8: Int8 = 42 // 8-bit integer

let int16: Int16 = 42 // 16-bit integer

let int32: Int32 = 42 // 32-bit integer

let int64: Int64 = 42 // 64-bit integer

// Floating Point Numbers
let float: Float = 3.14 // 32-bit

let double: Double = 3.14 // 64-bit

// Booleans
let boolean: Bool = true

// Strings
let string: String = "Hello, World!"

Optionals

// An optional represents a value that may or may not be present
var optional: Int? = nil

optional = 42

// Unwrap optionals
if let value = optional {
    print("The value is \(value)")
} else {
    print("The value is nil")
}

Arrays

// Initialization
var emptyArray = [Int]()
var array: [Int] = [1, 2, 3]
var shorthandArray = ["One", "Two", "Three"]

// Accessing Elements
let firstElement = array[0]
let lastElement = array.last
let elementAtIndex = array.index(after: 1)

// Adding Elements
array.append(4)
array += [5, 6, 7]
array.insert(0, at: 0)

// Removing Elements
array.removeLast()
array.removeFirst()
array.remove(at: 0)

// Iterating Over Elements
for element in array {
    print(element)
}

array.forEach { element in
    print(element)
}

Sets

// Initialization
var emptySet = Set<Int>()
var set: Set<Int> = [1, 2, 3]
var shorthandSet: Set = ["One", "Two", "Three"]

// Accessing Elements
if set.contains(1) {
    print("Set contains 1")
}

// Adding Elements
set.insert(4)

// Removing Elements
set.remove(3)

// Iterating Over Elements
for element in set {
    print(element)
}

set.forEach { element in
    print(element)
}

Dictionaries

// Initialization
var emptyDictionary = [String: Int]()
var dictionary: [String: Int] = ["One": 1, "Two": 2, "Three": 3]
var shorthandDictionary = ["One": 1, "Two": 2, "Three": 3]

// Accessing Elements
let value = dictionary["One"]

// Adding Elements
dictionary["Four"] = 4

// Removing Elements
dictionary["Three"] = nil

// Iterating Over Elements
for (key, value) in dictionary {
    print("\(key): \(value)")
}

dictionary.forEach { (key, value) in
    print("\(key): \(value)")
}

Tuples

// A tuple is a group of values
let coordinates = (x: 10, y: 20)

print(coordinates.x) // 10
print(coordinates.y) // 20

Type Aliases

typealias Name = String

let name: Name = "John"

Control Flow

// If-else statements
if 1 < 2 {
    print("1 is less than 2")
} else if 1 == 2 {
    print("1 is equal to 2")
} else {
    print("1 is greater than 2")
}

// Switch statements
let value = "dog"

switch value {
case "cat":
    print("It's a cat")
case "dog":
    print("It's a dog")
default:
    print("It's something else")
}

// For loops
for i in 0..<10 {
    print(i)
}

for item in array {
    print(item)
}

// While loops
while condition {
    // Code
}

repeat {
    // Code
} while condition

Functions

// A function is a named block of code that can be called
func add(x: Int, y: Int) -> Int {
    return x + y
}

let result = add(x: 5, y: 10)

// A function can return multiple values using a tuple
func split(name: String) -> (first: String, last: String) {
    let parts = name.split(separator: " ")
    let first = String(parts.first ?? "")
    let last = String(parts.last ?? "")
    return (first, last)
}

let names = split(name: "John Doe")

// A function can take a variable number of arguments
func sum(numbers: Int...) -> Int {
    var total = 0
    for number in numbers {
        total += number
    }
    return total
}

let total = sum(numbers: 1, 2, 3, 4, 5

Object-Oriented Programming

Classes

// A class is a blueprint for creating objects
class Person {
    var name: String
    var age: Int
    
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
    
    func sayHello() {
        print("Hello, my name is \(name)")
    }
}

let person = Person(name: "John", age: 30)
person.sayHello()

// Inheritance
class Student: Person {
    var studentId: String
    
    init(name: String, age: Int, studentId: String) {
        self.studentId = studentId
        super.init(name: name, age: age)
    }
}

let student = Student(name: "Jane", age: 20, studentId: "123")
student.sayHello()

Structs

A struct is a value type that allows you to encapsulate related properties and behaviors into a single entity. It is similar to a class but with some key differences:

  • A struct is always passed by value, whereas a class is passed by reference. This means that when you pass a struct as an argument to a function, a copy of the struct is created, and any changes made to the copy do not affect the original.
  • A struct cannot inherit from another struct or class.
  • A struct cannot be used as a superclass.
  • A struct is a value type, which means it is copied when assigned to another variable or constant.

In general, structs are best used for small, simple types that are not likely to be subclassed or modified after creation.

// Define a struct called "Person"
struct Person {
    var name: String
    var age: Int

    // A method that returns a greeting
    func sayHello() -> String {
        return "Hello, my name is \(name). I am \(age) years old."
    }
}

// Create an instance of the Person struct
let john = Person(name: "John", age: 30)

// Access the properties of the instance
print(john.name)    // Output: "John"
print(john.age)     // Output: 30

// Call the sayHello() method on the instance
print(john.sayHello())  // Output: "Hello, my name is John. I am 30 years old."

Protocols

// A protocol defines a set of methods and properties that a type can conform to
protocol Animal {
    var name: String { get set }
    
    func makeSound()
}

// Conforming to a protocol
class Dog: Animal {
    var name: String
    
    init(name: String) {
        self.name = name
    }
    
    func makeSound() {
        print("Woof!")
    }
}

let dog = Dog(name: "Buddy")
dog.makeSound()

// Protocol inheritance
protocol Mammal: Animal {
    var numberOfLegs: Int { get }
}

class Cat: Mammal {
    var name: String
    var numberOfLegs: Int
    
    init(name: String, numberOfLegs: Int) {
        self.name = name
        self.numberOfLegs = numberOfLegs
    }
    
    func makeSound() {
        print("Meow!")
    }
}

let cat = Cat(name: "Whiskers", numberOfLegs: 4)
cat.makeSound()

Extensions

// An extension adds new functionality to an existing type
extension Int {
    func square() -> Int {
        return self * self
    }
}

let number = 5
print(number.square())

// Extensions can also be used to conform to a protocol
extension Double: Animal {
    var name: String {
        return "Dog"
    }
    
    func makeSound() {
        print("Bark!")
    }
}

let animal: Animal = 3.14
animal.makeSound()

Error Handling

// Errors can be thrown using the throw keyword
enum MyError: Error {
    case someError
}

func doSomething() throws {
    throw MyError.someError
}

// Errors can be caught using a do-catch block
do {
    try doSomething()
} catch {
    print("An error occurred: \(error)")
}

// Multiple catch blocks can be used to handle different types of errors
do {
    try doSomething()
} catch MyError.someError {
    print("Some error occurred")
} catch {
    print("An unknown error occurred: \(error)")
}

More About Optionals

// An optional is a type that can either contain a value or be nil
var optionalString: String? = "Hello"

// To safely unwrap an optional, use if-let syntax
if let value = optionalString {
    print("The value is \(value)")
} else {
    print("The value is nil")
}

// Optional chaining can be used to call methods or access properties on an optional
let count = optionalString?.count

// Force unwrapping can be used when you know for sure that the optional contains a value
let nonOptionalString = optionalString!

// Implicitly unwrapped optionals are optionals that are automatically unwrapped
var implicitlyUnwrappedString: String! = "World"
let count = implicitlyUnwrappedString.count

// Nil coalescing operator can be used to provide a default value if an optional is nil
let optionalInt: Int? = nil
let intValue = optionalInt ?? 0

Concurrency

// Grand Central Dispatch (GCD) is a low-level API for managing concurrent operations
let queue = DispatchQueue(label: "com.example.myqueue")
queue.async {
    print("This code is running on a background thread")
}

// Dispatch barriers can be used to synchronize access to shared resources
var array = [1, 2, 3]
let barrierQueue = DispatchQueue(label: "com.example.barrierqueue", attributes: .concurrent)

barrierQueue.async(flags: .barrier) {
    array.append(4)
}

// Operations can be used to encapsulate work that can be executed concurrently
class MyOperation: Operation {
    override func main() {
        print("Running operation")
    }
}

let operationQueue = OperationQueue()

let operation = MyOperation()
operationQueue.addOperation(operation)

// Operation dependencies can be used to ensure that operations execute in a certain order
let operation1 = MyOperation()
let operation2 = MyOperation()

operation2.addDependency(operation1)

operationQueue.addOperation(operation1)
operationQueue.addOperation(operation2)

JSON & Network

Json Encoding

struct MyModel: Codable {
    let name: String
    let age: Int
}

let myModel = MyModel(name: "John", age: 30)

let encoder = JSONEncoder()
let data = try encoder.encode(myModel)

let jsonString = String(data: data, encoding: .utf8)

Json Decoding

let jsonString = "{\"name\":\"John\",\"age\":30}"
let jsonData = jsonString.data(using: .utf8)!

let decoder = JSONDecoder()
let myModel = try decoder.decode(MyModel.self, from: jsonData)

JSON Serialization

Swift provides built-in support for encoding and decoding JSON data using the JSONSerialization and Codable APIs.

let jsonString = """
    {
        "name": "John Smith",
        "age": 30,
        "email": "[email protected]"
    }
"""

let jsonData = jsonString.data(using: .utf8)!

do {
    let jsonObject = try JSONSerialization.jsonObject(with: jsonData)
    if let dict = jsonObject as? [String: Any] {
        let name = dict["name"] as? String ?? ""
        let age = dict["age"] as? Int ?? 0
        let email = dict["email"] as? String ?? ""
        print("Name: \(name), Age: \(age), Email: \(email)")
    }
} catch let error {
    print("Error deserializing JSON: \(error.localizedDescription)")
}

Codable

The Codable protocol provides a convenient way to encode and decode Swift types to and from JSON data. To use Codable, you define a struct or class that conforms to the protocol and specify the mapping between its properties and the JSON keys.

struct Person: Codable {
    var name: String
    var age: Int
    var email: String
}

let jsonString = """
    {
        "name": "John Smith",
        "age": 30,
        "email": "[email protected]"
    }
"""

let jsonData = jsonString.data(using: .utf8)!

do {
    let decoder = JSONDecoder()
    let person = try decoder.decode(Person.self, from: jsonData)
    print("Name: \(person.name), Age: \(person.age), Email: \(person.email)")
} catch let error {
    print("Error decoding JSON: \(error.localizedDescription)")
}

URLSession

URLSession is a powerful and flexible API for making network requests in Swift. It supports a wide range of use cases, from simple GET requests to more complex tasks like file uploads and downloads.

// create a URL object for the API endpoint
guard let url = URL(string: "https://api.slingacademy.com/v1/sample-data/products") else {
    fatalError("Invalid URL")
}

// create a URLRequest object with the URL and HTTP method
var request = URLRequest(url: url)
request.httpMethod = "GET"

// create a URLSession object
let session = URLSession.shared

// create a data task with the request and completion handler
let task = session.dataTask(with: request) { (data, response, error) in
    // check for errors
    if let error = error {
        print("Error: \(error.localizedDescription)")
        return
    }
    
    // check for a successful response
    guard let httpResponse = response as? HTTPURLResponse,
          (200...299).contains(httpResponse.statusCode) else {
        print("Error: Invalid response")
        return
    }
    
    // check if data was received
    guard let data = data else {
        print("Error: No data received")
        return
    }
    
    // convert the data to a Swift object
    do {
        let decoder = JSONDecoder()
        let posts = try decoder.decode([Post].self, from: data)
        print(posts)
    } catch {
        print("Error: \(error.localizedDescription)")
    }
}

// start the task
task.resume()

Asynchronous Programming

Dispatch Queues

let queue = DispatchQueue(label: "com.slingacademy.myqueue")

queue.async {
    // Perform work asynchronously
}

Dispatch Group

let group = DispatchGroup()

group.enter()
// Perform first task asynchronously
group.leave()

group.enter()
// Perform second task asynchronously
group.leave()

group.notify(queue: .main) {
    // Both tasks have completed
}

Completion Handlers

func loadData(completion: @escaping (Result<MyModel, Error>) -> Void) {
    let url = URL(string: "https://api.example.com/data")!
    var request = URLRequest(url: url)
    request.httpMethod = "GET"
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")

    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        guard let data = data, error == nil else {
            completion(.failure(error ?? NSError(domain: "Unknown error", code: 0, userInfo: nil)))
            return
        }
        
        do {
            let decoder = JSONDecoder()
            let myModel = try decoder.decode(MyModel.self, from: data)
            completion(.success(myModel))
        } catch let error {
            completion(.failure(error))
        }
    }
    
    task.resume()
}

File I/O

Writing to a File

let fileURL = URL(fileURLWithPath: "/path/to/file.txt")
let text = "Hello, world!"

do {
    try text.write(to: fileURL, atomically: true, encoding: .utf8)
} catch let error {
    print("Error writing to file: \(error.localizedDescription)")
}

Reading from a File

let fileURL = URL(fileURLWithPath: "/path/to/file.txt")

do {
    let text = try String(contentsOf: fileURL, encoding: .utf8)
    print(text)
} catch let error {
    print("Error reading from file: \(error.localizedDescription)")
}

Afterword

This Swift cheat sheet is very useful for quick lookup and review. I often use it in my work. You can also bookmark it for later use.

Topic examples are kept as concise as possible, so if you are new, it may be difficult to understand. Therefore, if you are a beginner, I recommend reading the detailed and specific tutorials about Swift on this website to get familiar with this programming language first.