Updated on

Swift Language

The only way to go swift, is to go well


Intro

The official Apple language.

Examples

Optionals

let optionalBool: Bool? = nil
let optionalInt: Int? = nil
let optionalStr: String? = nil

nil coalescing

let nonOptionalBool: Bool = optionalBool ?? false

if let

/// Without var creation
if let optionalBool, let optionalInt, let optionalStr {
    print("optionalBool, optionalInt AND optionalStr are not optional in here: \(optionalBool), \(optionalInt), \(optionalStr)")
} else {
    print("either optionalBool OR optionalInt OR optionalStr are nil")
}

/// With var creation
if let aBoolValue = optionalBool, let aIntValue = optionalInt, let aStrValue = optionalStr {
    print("aBoolValue, aIntValue AND aStrValue are not optional: \(aBoolValue), \(aIntValue), \(aStrValue)")
} else {
    print("either optionalBool OR optionalInt OR optionalStr are nil")
}

guard let

/// With var creation
guard let aBoolValue = optionalBool, let aIntValue = optionalInt, let aStrValue = optionalStr else {
    print("either optionalBool OR optionalInt OR optionalStr are nil, no variable was created")
}

/// A `guard` statement makes you sure that the created variables are not optional
print("aBoolValue, aIntValue AND aStrValue are not optional: \(aBoolValue), \(aIntValue), \(aStrValue)")
s
/// Without var creation
guard let optionalBool, let optionalInt, let optionalStr else {
    print("either optionalBool OR aIntValue OR aStrValue are nil, no variable was created")
}

print("optionalBool, optionalInt AND optionalStr are not optional anymore: \(optionalBool), \(optionalInt), \(optionalStr)")

Tuples

/// Access
let tuple: (String, Int) = ("One", 1)
print("Name: \(tuple.0), Value: \(tuple.1)")

let (name, value): (String, Int) = ("One", 1)
print("Name: \(name), Value: \(value)")

for (index, char) in "String".enumerated() {
    print("Index: \(index), Character: \(char)")
}

let letters: [(Int, Character)] = "String".enumerated().map { tuple in
    (tuple.offset, tuple.element)
}

print("First letter: \(letters.first!.1), Last letter: \(letters.last!.1)")

Enum

Raw values

/// `Int` protocol makes `Planet.mercury` have an EXPLICIT raw value of 1, `Planet.venus` have an IMPLICIT raw value of 2, and so on
enum Planet: Int {
    case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
}

/// `String` protocol makes `Color.red` have an IMPLICIT raw value of "red" and so on
enum Color: String {
    case red, green, blue
}

Iterating

/// `CaseIterable` protocol enables `CompassPoint.allCases` list
enum CompassPoint: CaseIterable {
    case north
    case south
    case east
    case west

    var direction: String {
        switch self {
        case .north:
            "Up"
        case .south:
            "Down"
        case .east:
            "Right"
        case .west:
            "Left"
        }
    }
}

print("There are \(CompassPoint.allCases.count) compass points.")

let go: CompassPoint = .west
print("Go \(go.direction)")

Associated values

enum Barcode {
    case upc(Int, Int, Int, Int)
    case qrCode(String)
}

var productBarcode = Barcode.upc(8, 85909, 51226, 3)

if case .upc(let numberSystem, _, _, let check) = productBarcode { // Unwrapping only two .ups values
    print("numberSystem: \(numberSystem), check: \(check)")
}

productBarcode = .qrCode("ABCDEFGHIJKLMNOP") // old values are lost

print(productBarcode)

Iterables and common iteration methods

let fruitsArray: [String] = ["Apple", "Orange", "Orange"]
if let firstFruit = fruitsArray.first {
    print("First fruit: \(firstFruit)")
}

var booleans: Array<Bool> = [true, false, true]
let falseCount = booleans.count(where: { element in
    !element
})

/// Adding elements
booleans.append(false)
booleans.append(contentsOf: [true, true])
booleans = booleans + [false, true]
booleans.insert(true, at: 0)
booleans.insert(contentsOf: [false, true], at: 1)
print("The last false is in: \(booleans.lastIndex(of: false) ?? 0)")

/// Sets
var fruitsSet: Set<String> = []
fruitsArray.forEach { fruitsSet.insert($0) }
print("fruitsSet: \(fruitsSet)")

filter

let trueCount = booleans.filter(\.self).count
print("trueCount: \(trueCount)")

let onlyFalses: [Bool] = booleans.filter({ !$0 }) // one-line shorthand
print("onlyFalses: \(onlyFalses)")

let fruitsWithA = fruits.filter { f in
    f.lowercased().starts(with: "a")
}
print("fruitsWithA: \(fruitsWithA)")

map

let uppercasedFruits = fruits.map { fruit in
    fruit.uppercased()
}
print("uppercasedFruits: \(uppercasedFruits)")

let booleansString = booleans.map(\.description)
print("booleansString: \(booleansString)")

sort

let sortedTrueFirst = booleans.sorted { a, b in
    a == true && b == false
}
print("sortedBooleans: \(sortedTrueFirst)")

/// Integer sorting method
func areInIncreasingOrder(a: Int, b: Int) -> Bool {
    a < b
}

let integers = [9, 4, 7, 8, 6, 1, 5, 2, 3, 0]
let sortedIntegers = integers.sorted(by: areInIncreasingOrder)
print("sortedIntegers: \(sortedIntegers)")

Dictionary

let empty: [String: Int] = [:]
var fruits: [String: [String]] = ["a": ["Apple"], "b": ["Banana"], "c": ["Carrot"]]

/// [] returns an optional
let fruitsWithA: [String]? = fruits["a"]
let fruitsWithZ: [String] = fruits["z"] ?? []

fruits["d"] = ["Durian"]
fruits["a"]?.append("Avocado")
print(fruits)

let json: [String: Any] = [
    "name": "Flank",
    "age": 29,
    "isPremium": false,
    "friends": ["Milano", "Bertrand"]
    "address": [
        "street": "Rua das Flores",
        "number": 123,
        "city": "São Paulo"
    ],
]

Loops

let seconds: Range<Int> = 0 ..< 60
let secs: ClosedRange<Int> = 0 ... 59
for num in secs {
    print(num)
}

let natoAlphabet = ["Alpha", "Bravo", "Delta", "Echo", "Foxtrot"]
for letter in natoAlphabet {
    print(letter)
}

for (index, second) in seconds.enumerated() {
    if index % 2 == 0 { continue }
    if second > 30 { break }
    print("second \(index) == \(second)")
}