# Swift / SwiftUI - Statically Typed [Building for Mac with VBox](https://medium.com/@twister.mr/installing-macos-to-virtualbox-1fcc5cf22801) ## Basics ### Macro ```swift #if DEBUG // contents compiled only if in DEBUG build #endif ``` ### Comments ```swift // single line comment /* multi line comment */ ``` ### Variables ```swift var variable = value // implicit variable init (auto-determine type) var variable: Type = value // explicit variable init var variable: Type? = value // explicit nullable variable init ``` ### Constants ```swift let CONSTANT = value // constant init (value can be assigned at runtime) ``` ### Console Output ```swift print() // empty line print(variable) print("string") ``` ## Strings ```swift var string "Text: \()" // string interpolation var string = "Hello" + "There" // string concatenation var multilineString = """Use double quotes trice to make a string span multiple lines""" ``` ## Array ```swift var array = ["firstItem", "secondItem", ...] var array = [Type()] // init empty homogeneous array array[index] // value access array[index] = value // value update array.append(item) // add item to the end array.contains(item) // membership check array.sort() // in place sort // Heterogeneous Array var list: Any = ["string", 47, ...] // cannot access with [index] var list: Any = [] // init empty heterogeneous array ``` ## Tuple A **tuple** type is a comma-separated list of types, enclosed in parentheses. It's possible to use a tuple type as the return type of a function to enable the function to return a single tuple containing multiple values. It's possible to name the elements of a tuple type and use those names to refer to the values of the individual elements. An element name consists of an identifier followed immediately by a colon (:). ```swift var tuple: (Type, Type) = (value, value) // explicit type var tuple = (value, value) // implicit type tuple.0 // item access // named elements var tuple = (name1: value1, name2: value2, ...) // tuple init tuple = (value1, value2) // names are inferred tuple.name1 // item access ``` ### Tuple Decomposition ```swift var tuple = (value1, value2) var (var1, var2) = tuple // var1 = value1, var2 = value2 ``` ## Type Identifier ```swift typealias Point = (Int, Int) var origin: (0, 0) ``` ## Dictionary ```swift var dict = [ "key": "value", ... ] var dict = [Type: Type]() // init empty dict dict[key] // value access dict[key] = value // value update ``` ## Expressions & Operators ### Primary Expressions | Syntax | Operation | |---------------------|---------------------------------------------------------------------| | x`.`m | access to member `m` of object `x` ("." --> member access operator) | | x`(...)` | method invocation ("()" --> method invocation operator) | | x`[...]` | array access and indicization | | `new` T(...) | object instantiation | | `x!` | declare x as not nil | ### Unary Operators | Operator | Operation | | --------- | --------------- | | `+`x | identity | | `-`x | negation | | `!`x | logic negation | | `~`x | binary negation | | `++`x | pre-increment | | `--`x | pre-decrement | | x`++` | post-increment | | x`--` | post decrement | | `(type)`x | explicit casting | ### Mathematical Operators | Operator | Operation | | -------- | ----------------------------------------------------- | | x `+` y | addition, string concatenation | | x `-` y | subtraction | | x `*` y | multiplication | | x `/` y | integer division, **always** returns an `int` | | x `%` y | modulo, remainder | | x `<<` y | left bit shift | | x `>>` y | right bit shift | ### Relational Operators | Operator | Operation | |----------|----------------------------------------| | x `<=` y | less or equal to | | x `>` y | greater than | | x `>=` y | greater or equal to | | x `is` T | `true` if `x` is an object of type `T` | | x `==` y | equality | | `!`x | inequality | ### Logical Operators | Operator | Operation | Name | |--------------|-------------------------------------------------------|------------------| | `~`x | bitwise NOT | | x `&` y | bitwise AND | | x `^` y | bitwise XOR | | x `|` y | bitwise OR | | x `&&` y | evaluate `y` only if `x` is `true` | | x `||` y | evaluate `y` only if `x` is `false` | | x `??` y | evaluates to `y` only if `x` is `nil`, `x` otherwise | nil coalescing | | x`?.`y | stop if `x == nil`, evaluate `x.y` otherwise | nil conditional | ### Assignment | Operator | Operation | |-----------|------------------------| | x `+=` y | x = x + y | | x `-=` y | x = x - y | | x `*=` y | x = x * y | | x `/=` y | x = x / y | | x `%=` y | x = x % y | | x `<<=` y | x = x << y | | x `>>=` y | x = x >> y | | x `&=` y | x = x & y | | x `|=` y | x = x | y | | x `^=` y | x = x ^ y | | x `??=` y | if (x == nil) {x = y} | ### Conditional Operator ` ? : ;` ### Nil Checks ```swift variable ?? value // same as if(variable == nil) { variable = value } ``` ## If-Else ```swift if condition { // code here } else if condition { //code here } else { // code here } if let var0 = var1 { /* statements */ } // same as let var0 = var1 if var0 != nil { /* statements */ } ``` ### Switch ```swift switch { case : // code here break // can be implicit case key where : // code here break default: // code here break } ``` ## Loops ### For Loop ```swift // range based for for i in start...end { /* statements */ } // end included for i in start.. Type { //code here return } func funcName(param: Type) -> Type { // implicit return } // func call MUST have parameter's names funcName(param: value, ...) // multiple return values func funcMultipleParameters(param: Type) -> (retVal1: Type, retVal2: Type) { //code here return (, ) } var result = funcMultipleReturns(param: value) result.retVal1 // access to tuple components // argument labels (only first label can be omitted) func funcWithLabels(_ param: Type, label param: Type, ...) -> Type { } funcWithLabels(value, label: value, ...) ``` ### Passing Functions as Parameters ```swift func f(param: Type) -> Type {} func g(f: (Type) -> Type) {} // (Type) -> Type are the passed func input and output types ``` ### Functions Returning Functions ```swift func f() -> ((Type) -> Type) { func g(param: Type) -> type {} return g } ``` ## [Closure](https://docs.swift.org/swift-book/LanguageGuide/Closures.html) (`{ .. }`) **Closures** are self-contained blocks of functionality that can be passed around and used in code. Closures in Swift are similar to blocks in C and Objective-C and to lambdas in other programming languages. ```swift { (parameters: Type) -> Type in // statements } { parameters in return } // type inference from context { $0 > $1 } // $ identifies the n-th argument, IN can be omitted if closure has only the body ``` ## [Enums](https://docs.swift.org/swift-book/LanguageGuide/Enumerations.html) ### Enum Definition ```swift enum EnumName { case key1 case key2 case ... } EnumName.key1 // key1 ``` ### Enum with Raw Values ```swift enum EnumName: Type { case key1 = value case key2 = value case ... } EnumName.key1.rawValue // value enum IntegerEnum: Int { // the value of each case is one more then the previous case case one = 1 case two, three, four case ... } ``` ### Matching Enumeration Values with a Switch Statement ```swift enum Rank: Int { case ace = 1, two, three, four, five, six, seven, eight, nine, ten case jack, queen, king func getValue() -> String { switch self { case .jack: return "jack" case .queen: return "queen" case .king: return "king" default: return String(self.rawValue) } } } Rank.jack.getValue() // "jack" Rank.jack.rawValue // 11 ``` ## Struct (Value Type) ```swift struct StructName { var attribute = value // instance variable private var _attribute: Type // backing field for property var property: Type { get { return _attribute } set { _attribute = newValue } // newValue contains the passed value // OR set(param) { _attribute = param } } // constructor init(param: Type) { self.attribute = param // attribute valorization } // de-initializer (free memory containing obj?) deinit { // empty the attributes } // overloading func method() -> Type { } func method(param: Type, ...) -> Type { } } var structure = StructName() // struct instantiation ``` ## Classes (Reference Type) ### Class Definition & Instantiation ```swift class ClassName { var attribute = value // instance variable private var _attribute: Type // backing field for property var property: Type { get { return _attribute } set { _attribute = newValue } // newValue contains the passed value // OR set(param) { _attribute = param } } // constructor init(param: Type) { self.attribute = param // attribute valorization } // de-initializer (free memory containing obj?) deinit { // empty the attributes } // overloading func method() -> Type { } func method(param: Type, ...) -> Type { } } var obj = ClassName() // obj instantiation ``` ### Property Observers `willSet` & `didSet` Do actions before/after modifying a property value. > **Note**: `willSet` and `didSet` do not *set* the value of the property. ```swift class ClassName { var _attribute: Type var property { get { return _attribute } set{ _attribute = newValue } willSet { // act before setting the property value } didSet { // act after setting the property value } } } ``` ### Inheritance ```swift class Derived: SuperClass { var attribute: Type init(param1: Type, param2: Type) { self.attribute = param1 super.init(param: param2 ) // superclass init (NEEDED) } // overriding override func method() {} } ``` ### Exception Handling ```swift guard let variable = else { /* statements */ // throw or return to exit code branch } do { try } catch { // statements } ```