Core Wiki

Swift

References

In Swift structs are value types whereas classes are reference types. When you copy a struct, you end up with two unique copies of the data. When you copy a class, you end up with two references to one instance of the data. It's a crucial difference, and it affects your choice between classes or structs.

Syntax

var str: String = "Hello Darwin" // mutable
let str2: String = "Sup dawg" // immutable 
print("str is equal to \(str)")

Selector shortcuts

SomeObject.animation(.easeInOut)
SomeObject.animation(Animation.easeInOut)

Dot notation example

enum Season: String, CaseIterable {
    case spring = "🌷"
    case summer = "🌞"
    case autumn = "🍂"
    case winter = "☃️"
}
 
func printSeason(s: Season) {
    print(s.rawValue)
}
 
printSeason(s: .spring)

Optional unwrapping

class Person {
    var name: String?
}
 
let person = Person()
person.name = "John Doe"
 
print(person.name) //Optional("John Doe")
print(person.name!) //John Doe

Types are all upper case:

String, Int, Float, Double

Casting:

let x:Int = 3;
print("I'm a float now \(Float(x))")
 
let myAge = "20";
let myAgeInt = myAge.toInt();
let myAgeFloat = (myAge as NSString).floatValue

Optionals

let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
// convertedNumber is inferred to be of type "Int?", or "optional Int"

Optional binding

if let constantName = someOptional {
    statements
}
 
if let actualNumber = Int(possibleNumber) {
    print("The string \"\(possibleNumber)\" has an integer value of \(actualNumber)")
} else {
    print("The string \"\(possibleNumber)\" could not be converted to an integer")
}

Data structures

Array

Get first n elements of array

Array(my_array.prefix(n))
my_array.shuffled()

Iterate

ForEach(0...my_array.count, id:\.self) { number in
}

Chunking arrays into subarrays of size

extension Array {
    func chunked(into size: Int) -> [[Element]] {
        return stride(from: 0, to: count, by: size).map {
            Array(self[$0..<Swift.min($0+size, count)])
        }
    }
}
 
let subarrays = my_array.chunked(into: 2)

Filter array

my_array.filter{ $0.isSpicy == true}

String

Formatting

String(format: "$%.2f", self.total)

Dictionary

var categories: [String: [Landmark]] {
    Dictionary(
        grouping: landmarkData,
        by: { $0.category.rawValue }
    )
}

Property Wrappers

@propertyWrapper
class UpperCase {
    private(set) var value: String = ""
 
    var wrappedValue: String {
        get { value }
        set {
            value = newValue.uppercased()
        }
    }
}
 
struct Driver {
 
    @UpperCase
    var license: String
 
    @UpperCase
    var state: String
}
 
extension Driver {
    init(license: String) {
        self.license = license
    }
}
 
var driver = Driver(license: "ert567")
driver.state = "tx"
 
print(driver.license) //ERT567
print(driver.state) //TX

Protocols

Identifiable

class OrderViewModel: Identifiable {
    var name = ""
    var type = ""
}

This creates id for every instance of the class which can be used in forEach

ForEach(self.orderListVM.orders, id:\.id) { order in
}

Data Storage

Load/Save user defaults using singleton pattern

import Foundation
 
class SettingsViewModel: ObservableObject {
 
    static let shared = SettingsViewModel()
 
    @Published var isOn: Bool = UserDefaults.standard.bool(forKey: "isOn") {
        didSet {
            UserDefaults.standard.set(self.isOn, forKey: "isOn")
        }
    }
 
    private init() {}
}
@ObservedObject var settingsVM = SettingsViewModel.shared

Closures

Example of escaping closure

func simulateLogin(completion: @escaping (Bool) -> ()) {
    completion(false)
}
 
simulateLogin() { status in 
    print(status)
}