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.
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") }
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}
Formatting
String(format: "$%.2f", self.total)
var categories: [String: [Landmark]] { Dictionary( grouping: landmarkData, by: { $0.category.rawValue } ) }
@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
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 }
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
Example of escaping closure
func simulateLogin(completion: @escaping (Bool) -> ()) { completion(false) } simulateLogin() { status in print(status) }